轉(zhuǎn)載請(qǐng)注明來(lái)源 賴(lài)賴(lài)的博客
導(dǎo)語(yǔ)
學(xué)習(xí)妻柒,先知骨架扛拨,再豐羽翼,先知其然举塔,再知其所以然绑警。
要迅速解決問(wèn)題,首先要有一個(gè)自己的框架知識(shí)庫(kù)央渣,例如计盒,我知道Tomcat可以搭建web服務(wù)器,我知道Spring MVC可以構(gòu)件web項(xiàng)目芽丹,我知道Mybatis可以控制持久層...
這些是需要了解并且記在腦中的北启,至于詳細(xì)的東西,等用的時(shí)候可以詳細(xì)了解拔第,此博客專(zhuān)題連載的Spring系列咕村,就是送你一套框架知識(shí)庫(kù)
今天介紹單元測(cè)試,簡(jiǎn)單實(shí)例蚊俺,讓你知其然懈涛。
實(shí)例
項(xiàng)目工程目錄結(jié)構(gòu)和代碼獲取地址
獲取地址(版本Log將會(huì)注明每一個(gè)版本對(duì)應(yīng)的課程)
https://github.com/laiyijie/SpringLearning
目錄結(jié)構(gòu)
運(yùn)行工程(與之前不同,請(qǐng)注意)
運(yùn)行方式
- 右鍵HelloInterFaceTest.java
- Run as
- JUnit Test
運(yùn)行結(jié)果
init before every testcase
the 10 time to say userHello
clean after every testcase
init before every testcase
time:1480420925632 userHello
clean after every testcase
項(xiàng)目詳解
從HelloInterFaceTest.java入手(終于不是四行代碼的App.java啦)
HelloInterFaceTest.java
package me.laiyijie.demo.service;
import org.junit.After;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:root-context.xml" })
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class HelloInterFaceTest {
@Autowired
private HelloInterface helloInterface;
@Before
public void init() {
System.out.println("init before every testcase");
}
@After
public void after() {
System.out.println("clean after every testcase");
}
@Test
public void TS0101_sayHello_normal() {
int num = 10;
String result = helloInterface.sayHello(num);
System.out.println(result);
String expect = "the " + num + " time to say userHello";
assertEquals(expect, result);
}
@Test
public void TS0201_sayHelloWithTime_normal() {
String result = helloInterface.sayHelloWithTime();
System.out.println(result);
}
}
代碼有點(diǎn)兒長(zhǎng)泳猬?莫慌批钠,長(zhǎng)代碼,一個(gè)套路得封,那就是疊磚埋心!讓我們仔細(xì)看看這塊磚
JUnit測(cè)試用例執(zhí)行過(guò)程概述
首先略過(guò)頭部,直接看類(lèi)里面的方法呛每,其中兩個(gè)函數(shù)分別被@Before
和@After
注解踩窖,兩個(gè)函數(shù)被@Test
注解。
我們仔細(xì)看一下運(yùn)行結(jié)果可以發(fā)現(xiàn)幾個(gè)函數(shù)的執(zhí)行順序如下所示:
-
@Before
注解的函數(shù)先執(zhí)行 -
@Test
注解的TS0101_sayHello_normal
執(zhí)行 -
@After
注解的函數(shù)執(zhí)行 -
@Before
注解的函數(shù)先執(zhí)行 -
@Test
注解的TS0201_sayHelloWithTime_normal
執(zhí)行 -
@After
注解的函數(shù)執(zhí)行
那么顯而易見(jiàn)的結(jié)論:
-
@Test
注釋的函數(shù)會(huì)挨個(gè)執(zhí)行(我們稱(chēng)這個(gè)函數(shù)為測(cè)試用例) -
@Before
注解的函數(shù)會(huì)在每個(gè)@Test
注解的函數(shù)之 前 執(zhí)行(我們使用這個(gè)注解進(jìn)行測(cè)試用例前的初始化) -
@After
注解的函數(shù)會(huì)在每個(gè)@Test
注解的函數(shù)之 后 執(zhí)行(我們使用這個(gè)注解進(jìn)行測(cè)試用例后的清理)
下面詳細(xì)解讀其余部分:
import先略過(guò)晨横,只是一些依賴(lài)
之后從類(lèi)前面的注解開(kāi)始講解
Spring測(cè)試類(lèi)前注解含義(啟動(dòng)Spring測(cè)試環(huán)境)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:root-context.xml" })
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-
@RunWith(SpringJUnit4ClassRunner.class)
提供了一個(gè)Spring的運(yùn)行環(huán)境洋腮,說(shuō)白了,就是可以在測(cè)試類(lèi)中使用@Autowired
等Spring注解手形,例如代碼中的private HelloInterface helloInterface;
就是使用@Autowired
來(lái)注入啥供,你完全可以理解為是@Service
-
@ContextConfiguration({ "classpath:root-context.xml" })
加載了root-context.xml
(加載了才可以注入UserServiceImpl
實(shí)例嘛 -
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
根據(jù)用例的函數(shù)名稱(chēng)升序執(zhí)行用例(很實(shí)用,但是非必須)
OK库糠,三個(gè)注解解決了Spring+JUnit單元測(cè)試環(huán)境的配置伙狐。
JUnit的三個(gè)注解涮毫,加上Spring Test環(huán)境的配置,測(cè)試用例就此簡(jiǎn)單起步贷屎。
而在測(cè)試用例中罢防,我們肯定不能通過(guò)System.out.println
輸出到控制臺(tái)來(lái)進(jìn)行判斷(肉眼判斷輸出是否正確,很容易出現(xiàn)失誤)
在此我簡(jiǎn)單的介紹使用Assert
類(lèi)提供的方法判斷輸出是否正確
assertequals唉侄,跟肉眼say goodbye
我們摘出這段代碼:
@Test
public void TS0101_sayHello_normal() {
int num = 10;
String result = helloInterface.sayHello(num);
System.out.println(result);
String expect = "the " + num + " time to say userHello";
assertEquals(expect, result);
}
其中這句話:
assertEquals(expect, result);
就這么簡(jiǎn)單咒吐,第一參數(shù)為期望輸出
第二個(gè)參數(shù)為真實(shí)結(jié)果
。
- 如果兩者相等(equals)属划,用例通過(guò)(JUnit測(cè)試條為綠色)
- 如果兩者不等恬叹,用例失敗(JUnit測(cè)試條為紅色)
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.laiyijie</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.2.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
新增兩個(gè)Scope為test的依賴(lài)同眯,分別是
-
spring-test
提供@RunWith
中的SpringJUnit4ClassRunner.class
以及@ContextConfiguration
-
junit
提供@RunWith
绽昼,@After
,@Before
须蜗,@Test
等
小結(jié):
- JUnit運(yùn)行過(guò)程
- 通過(guò)
@RunWith(SpringJUnit4ClassRunner.class)
和@ContextConfiguration({ "classpath:root-context.xml" })
配置Spring單元測(cè)試環(huán)境硅确,使得- 加載
root-context.xml
配置的ApplicationContext
- 使得
HelloInterFaceTest
(測(cè)試類(lèi))可以使用@Autowired
裝載容器中的bean
- 加載
- 通過(guò)
@Before
實(shí)現(xiàn)測(cè)試用例運(yùn)行前初始化 - 通過(guò)
@Test
定義測(cè)試用例并且挨個(gè)執(zhí)行 - 通過(guò)
@After
實(shí)現(xiàn)測(cè)試用例完成后清理
- 通過(guò)
測(cè)試用例這么好寫(xiě),何不多寫(xiě)幾個(gè)唠粥?你的代碼穩(wěn)定性會(huì)提升一個(gè)層次疏魏!