單元測(cè)試筆記

單元測(cè)試(unit test)為了驗(yàn)證程序的正確性
必要性:
預(yù)防Bug,快速定位Bug,提高代碼質(zhì)量,減少耦合,減少調(diào)試時(shí)間,減少重構(gòu)風(fēng)險(xiǎn)
SpringBoot的測(cè)試庫(kù).

● Spring Test & Spring Boot Test : SpringBoot提供的應(yīng)用程序功能集成化測(cè)試支持许昨。
● Junit : Java 應(yīng)用程序單元測(cè)試標(biāo)準(zhǔn)類(lèi)庫(kù)。
● AssertJ :輕量級(jí)的斷言類(lèi)庫(kù)北启。
● Hamcrest :對(duì)象匹配器類(lèi)庫(kù)。
● Mockito : Java Mock 測(cè)試框架。
● JsonPath : JSON 操作類(lèi)庫(kù)咕村。
JSONassert :用于 JSON 的斷言庫(kù)场钉。
1.了解回歸測(cè)試框架 JUnit
JUnit 是對(duì)程序代碼進(jìn)行單元測(cè)試的 Java 框架。ビ用米癰與自切化測(cè)試工具懈涛,降低
減少煩瑣性惹悄,并有效避免出現(xiàn)程序錯(cuò)誤。
JUnit 測(cè)試是白盒測(cè)試(因?yàn)橹罍y(cè)試如何完成功能和完成什么樣的功能)肩钠。要使用只需要繼承 TestCase 類(lèi)。


JUnit 提供以下注解暂殖。
@ BeforeClass :在所有測(cè)試單元前執(zhí)行一次价匠,一般用來(lái)初始化整體的代碼。@ AfterClass :在所有測(cè)試單元后執(zhí)行一次呛每,一般用來(lái)銷(xiāo)毀和釋放資源踩窖。
@ Before :在每個(gè)測(cè)試單元前執(zhí)行,一股用來(lái)初始化方法晨横。
@ After :在每個(gè)測(cè)試單元后執(zhí)行洋腮,一般用來(lái)回滾測(cè)試數(shù)據(jù)。.@ Test :編寫(xiě)測(cè)試用例手形。
@ Test ( timeoyt =1000):對(duì)測(cè)試單元進(jìn)行限時(shí)啥供。這里的“1000”表示若超過(guò)1s
測(cè)試失敗。單位是 m 京尬女子蛋間年一點(diǎn)
@ Test ( expedted = Exception . class ):指定測(cè)試單期望得到的異常類(lèi)库糠。如果執(zhí)沒(méi)有拋出指定的異常伙狐,則測(cè)試失敗。
@ Ignore :執(zhí)行測(cè)試時(shí)將忽略掉此方法瞬欧。如果用于修飾類(lèi)贷屎,則忽略整個(gè)類(lèi)。
@ RunWith :在 JUnit 中有很多 Runner ,它們負(fù)責(zé)調(diào)用測(cè)試代碼艘虎。每個(gè) Runner 功能唉侄,應(yīng)根據(jù)需要選擇不同的 Runner 來(lái)運(yùn)行測(cè)試代碼。


這里注意:如果Assert.assertThat過(guò)期了野建,那么可以用Hamcrest.assertThat替代
創(chuàng)建單元測(cè)試 :
User

package com.example.demo;

import lombok.Data;

/**
 * Copyfright(C),2022-2022,復(fù)興元宇科技有限公司
 * FileName:User Author:yz Date:2022/3/18 19:29
 */
@Data
public class User {
    private String name;
    private int age;
}

UserService

package com.example.demo;

import org.springframework.stereotype.Service;

/**
 * Copyfright(C),2022-2022,復(fù)興元宇科技有限公司
 * FileName:UserService Author:yz Date:2022/3/18 19:30
 */
@Service
public class UserService {
    public User getUserInfo(){
        User user = new User();
        user.setName("wangchaung");
        user.setAge(18);
        return user;
    }
}

HelloController

package com.example.demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Copyfright(C),2022-2022,復(fù)興元宇科技有限公司
 * FileName:HelloController Author:yz Date:2022/3/18 19:07
 */
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello(String name){
        return "hello " + name;
    }
}

在Test目錄下創(chuàng)建類(lèi)HelloControllerTest

package com.example.demo;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

/**
 * Copyfright(C),2022-2022,復(fù)興元宇科技有限公司
 * FileName:HelloControllerTest Author:yz Date:2022/3/18 19:12
 */
public class HelloControllerTest {
    @Autowired
    private WebApplicationContext webApplicationContext;
    private MockMvc mockMvc;

    @Before
    public void setUp() throws Exception{
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void hello() throws Exception{
        MvcResult mvcResult = (MvcResult) mockMvc.perform(MockMvcRequestBuilders.get("/hello")
                .contentType("pplication/json;charset=UTF-8")
                .param("wangchuang")
                .accept("pplication/json;charset=UTF-8"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.content().string("hello wangchuang"))
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
        int status = mvcResult.getResponse().getStatus();
        String content = mvcResult.getResponse().getContentAsString();
        Assert.assertEquals(200,status);
        Assert.assertEquals("hello wangchuang",content);
    }
}

UserServiceTest運(yùn)行

package com.example.demo;

import org.hamcrest.MatcherAssert;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.regex.Matcher;

import static org.hamcrest.Matchers.is;

/**
 * Copyfright(C),2022-2022,復(fù)興元宇科技有限公司
 * FileName:UserServiceTest Author:yz Date:2022/3/18 19:32
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    private UserService userService;
    @Test
    public void getUserInfo(){
        User user = userService.getUserInfo();
        Assert.assertEquals(18,user.getAge());
//        Assert.assertThat(user.getName(),is("wangchuang"));
        MatcherAssert.assertThat("wancghuang",is(user.getName()));
    }
}

控制臺(tái)打印運(yùn)行結(jié)果:


result.png

Service層單元測(cè)試:

User同上
服務(wù)類(lèi)如下:

package com.example.demo.service;

import com.example.demo.entity.User;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    public User getUserInfo(){
        User user = new User();
        user.setName("zhonghua");
        user.setAge(18);
        return user;
    }
}

編寫(xiě)測(cè)試:
同上

Respository層的單元測(cè)試

Responsitory層主要對(duì)數(shù)據(jù)進(jìn)行增刪改查
Card.class

package com.example.demo.entity;

import lombok.Data;

import javax.persistence.*;

@Entity
@Table(name = "cardtestjpa")
@Data
public class Card {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private Integer num;
 }

CardRepository.interface

package com.example.demo.repository;


import com.example.demo.entity.Card;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CardRepository extends JpaRepository<Card,Long> {
    Card findById(long id);
}

Service

package com.example.demo.service;



import com.example.demo.entity.Card;

import java.util.List;

public interface CardService {
    public List<Card> getCardList();
    public Card findCardById(long id);
}

CardServiceImpl.implements

package com.example.demo.service.impl;


import com.example.demo.entity.Card;
import com.example.demo.repository.CardRepository;
import com.example.demo.service.CardService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public class CardServiceImpl implements CardService {
    @Autowired
    private CardRepository cardRepository;

    @Override
    public List<Card> getCardList() {
        return cardRepository.findAll();
    }

    @Override
    public Card findCardById(long id) {
        return cardRepository.findById(id);
    }
}

doTest

package com.example.demo.repository;

import com.example.demo.entity.Card;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

import static org.junit.Assert.*;

@RunWith(SpringRunner.class)
// SpringJUnit支持属划,由此引入Spring-Test框架支持!
//啟動(dòng)整個(gè)spring的工程
@SpringBootTest
//@DataJpaTest
@Transactional
//@Rollback(false)
public class CardRepositoryTest {
    @Autowired
    private  CardRepository  cardRepository;
    @Test
  public void testQuery() {
   // 查詢操作
  List<Card> list = cardRepository.findAll();
        for (Card card : list) {
            System.out.println(card);
        }
   }
    @Test
    public void testRollBank() {
        // 查詢操作
        Card card=new Card();

        card.setNum(3);
        cardRepository.save(card);
        //throw new RuntimeException();
    }
}

JPA和MySQL和單元測(cè)試junit的依賴

<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

Applicaiton.properities中關(guān)于Mysql的一點(diǎn)配置

spring.datasource.url=jdbc:mysql://127.0.0.1/book?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
spring.datasource.username=root
spring.datasource.password=rootroot
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true

spring.thymeleaf.cache=false
server.port=8080

在IDEA中JPA的實(shí)體創(chuàng)建方式

New-JPA-Entity-[Card]
Name:類(lèi)名字
EntityType:Entity
Id:int
Idgeneration:Identity
Select OK

在IDEA中快速創(chuàng)建Responsitory

New-SpringData-Respository
Entity:上一步創(chuàng)建的[Card]
inputName

其他說(shuō)明:

@Transactional:數(shù)據(jù)回滾的意思贬墩。所有方法執(zhí)行完了以后榴嗅,回滾成原來(lái)的樣子。在實(shí)際的測(cè)試代碼中陶舞,如果將改注解注釋掉嗽测,數(shù)據(jù)是不會(huì)回滾的。

單元測(cè)試中的數(shù)據(jù)回滾代碼

嚼一路辛苦,飲一路汗水_胫唷疏魏!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晤愧,隨后出現(xiàn)的幾起案子大莫,更是在濱河造成了極大的恐慌,老刑警劉巖官份,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件只厘,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡舅巷,警方通過(guò)查閱死者的電腦和手機(jī)羔味,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钠右,“玉大人赋元,你說(shuō)我怎么就攤上這事§浚” “怎么了搁凸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)狠毯。 經(jīng)常有香客問(wèn)我护糖,道長(zhǎng),這世上最難降的妖魔是什么垃你? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任椅文,我火速辦了婚禮,結(jié)果婚禮上惜颇,老公的妹妹穿的比我還像新娘皆刺。我一直安慰自己,他們只是感情好凌摄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布羡蛾。 她就那樣靜靜地躺著,像睡著了一般锨亏。 火紅的嫁衣襯著肌膚如雪痴怨。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天器予,我揣著相機(jī)與錄音浪藻,去河邊找鬼。 笑死乾翔,一個(gè)胖子當(dāng)著我的面吹牛爱葵,可吹牛的內(nèi)容都是我干的施戴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼萌丈,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赞哗!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起辆雾,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肪笋,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后度迂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體藤乙,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年惭墓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了湾盒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诅妹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出毅人,到底是詐尸還是另有隱情吭狡,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布丈莺,位于F島的核電站划煮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏缔俄。R本人自食惡果不足惜弛秋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望俐载。 院中可真熱鬧蟹略,春花似錦、人聲如沸遏佣。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)状婶。三九已至意敛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間膛虫,已是汗流浹背草姻。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稍刀,地道東北人撩独。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親跌榔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子异雁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 前言 進(jìn)入大廠已經(jīng)有一段時(shí)間了,這段時(shí)間確實(shí)接觸了在外面未曾接觸到很多東西僧须。而在外界津津樂(lè)道的進(jìn)階知識(shí)點(diǎn)(什么na...
    yjy239閱讀 1,987評(píng)論 0 7
  • 2016年4月11日 [TOC] 1纲刀、環(huán)境搭建(版本3.0) Android單元測(cè)試需要JUnit框架的支持,Ro...
    liucloo閱讀 1,358評(píng)論 1 1
  • junit特性 項(xiàng)目多元化担平,導(dǎo)致最基本的功能有時(shí)難以應(yīng)付示绊。所以,junit自4.x發(fā)布以來(lái)暂论,每次新版本的推出都引入...
    juconcurrent閱讀 1,620評(píng)論 0 10
  • 前端自動(dòng)化測(cè)試 一般情況下寫(xiě)單元測(cè)試的時(shí)間是業(yè)務(wù)時(shí)間的2倍 一般用于測(cè)試類(lèi)庫(kù)面褐、核心邏輯,組件庫(kù)(保證程序的健壯性 ...
    金剛狼_3e31閱讀 133評(píng)論 0 0
  • JUnit是java開(kāi)發(fā)人員的一個(gè)主要的測(cè)試工具取胎,做Android開(kāi)發(fā)同樣是離不開(kāi)java的展哭,所以Android單...
    云飛揚(yáng)1閱讀 8,173評(píng)論 0 56