什麼是Junit?
Junit是xUnit的一個子集,在c++,paython,java語言中測試框架的名字都不相同
xUnit是一套基於測試驅動開發的測試框架
其中的斷言機制:將程式預期的結果與程式執行的最終結果進行比對,確保對結果的可預知性
java所用的測試工具是Junit
使用 JUnit 需要匯入 JUnit 包。官方網站:https://junit.org/junit5/
在不同編譯器下的導包過程不一樣,這裡以 Maven 為例
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
測試流程
建立測試檔案
- 新建一個原始碼目錄來存放我們的測試程式碼
- 測試類的包應該和被測試類保持一致
- 測試方法上必須使用
@Test
進行修飾 - 測試方法必須使用 public void 進行修飾,不能帶任何的引數
- 測試單元中的每個方法必須可以獨立測試,測試方法間不能有任何的依賴
- 測試類使用 Test 作為類名的字尾(不是必須)
- 測試方法使用 test 作為方法名的字首(不是必須)
目的碼:
package com.imooc.util;
public class Calculate {
public int add(int a,int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
public int multiply(int a,int b) {
return a * b;
}
public int divide(int a ,int b) {
return a / b;
}
}
建立測試程式碼
右鍵選中需要測試的目的碼,建立 JUnit Test Case 測試用例。
測試程式碼:
package com.imooc.util;
import static org.junit.Assert.*;
import org.junit.Test;
public class CalculateTest {
/*
* 1.測試方法上必須使用@Test進行修飾
* 2.測試方法必須使用public void 進行修飾,不能帶任何的引數
* 3.新建一個原始碼目錄來存放我們的測試程式碼
* 4.測試類的包應該和被測試類保持一致
* 5.測試單元中的每個方法必須可以獨立測試,測試方法間不能有任何的依賴
* 6.測試類使用Test作為類名的字尾(不是必須)
* 7.測試方法使用test作為方法名的字首(不是必須)
*/
@Test
public void testAdd() {
assertEquals(6, new Calculate().add(3,3));
}
@Test
public void testSubtract() {
assertEquals(3, new Calculate().subtract(5,2));
}
@Test
public void testMultiply() {
assertEquals(4, new Calculate().multiply(2, 2));
}
@Test
public void testDivide() {
assertEquals(3, new Calculate().divide(6, 2));
}
}
注意:
- Failure 一般由單元測試使用的斷言方法判斷失敗所引起的,這表示在測試點發現了問題,即 程式輸出的結果和我們預期的不一樣。
- error 是由程式碼異常引起的,它可以產生於測試程式碼本身的錯誤,也可以是被測試程式碼中的一個隱藏 bug。
- 測試用例不說用來證明你是對的,而是用來證明你沒有錯
註釋
演示程式碼:
package com.imooc.util;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class JunitFlowTest {
/*
* 1.@BeforeClass修飾的方法會在所有方法被呼叫前被執行,
* 而且該方法是靜態的,所以當測試類被載入後接著就會執行它,
* 而且在記憶體中它只會存在一份例項,它比較適合載入配置檔案。
* 2.@AfterClass所修飾的方法通常用來對資源的清理,如關閉資料庫的連線
* 3.@Before和@After會在每個測試方法的前後各執行一次。
*
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("this is beforeClass...");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("this is afterClass...");
}
@Before
public void setUp() throws Exception {
System.out.println("this is before...");
}
@After
public void tearDown() throws Exception {
System.out.println("this is after");
}
@Test
public void test1() {
System.out.println("this is test1...");
}
@Test
public void test2(){
System.out.println("this is test2...");
}
}
執行結果:
隱藏的固定程式碼:
@BeforeClass
修飾的方法會在所有方法被呼叫前被執行,而且該方法是靜態的,所以當測試類被載入後接著就會執行它,而且在記憶體中它只會存在一份例項,它比較適合載入配置檔案以及一些只用載入一次的東西。@AfterClass
所修飾的方法通常用來堆資源的清理,如關閉資料庫的連線@Before
和@After
會在每個測試方法的前後各執行一次。這些都是固定程式碼,執行時一定會被執行
常用註釋:
@Test
:將一個普通的方法修飾成為一個測試方法@Test(expected=XX.class)
@Test(timeout=毫秒)
@BeforeClass
:它會在所有的方法執行前被執行,static 修飾@AfterClass
:它會在所有的方法執行結束後被執行,static 修飾@Before
:會在每一個測試方法被執行前執行一次@After
:會在每一個測試方法執行後被執行一次@Ignore
:所修飾的測試方法會被測試執行器忽略@RunWith
:可以更改測試執行器(如想自定義測試執行器可繼承 org.junit.runner.Runner)
可以配合測試套件使用。
測試套件
測試套件:可以組織測試類一起執行。
- 寫一個作為測試套件的入口類,這個類裡不包含其他的方法
- 更改測試執行器為
@RunWith(Suite.class)
- 將要測試的類作為陣列傳入到
@Suite.SuiteClasses({A,B,...})
演示程式碼:
package com.imooc.util;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({TaskTest1.class,TaskTest2.class,TaskTest3.class})
public class SuiteTest {
/*
* 1.測試套件就是組織測試類一起執行的
*
* 寫一個作為測試套件的入口類,這個類裡不包含其他的方法
* 更改測試執行器Suite.class
* 將要測試的類作為陣列傳入到Suite.SuiteClasses({})
*/
}
這段程式碼可以將 TaskTest1、2、3 同時執行測試。從而達到測試套件的效果。
引數化設定
- 更改預設的測試執行器為
@RunWith(Parameterized.class)
- 宣告變數來存放預期值和結果值
- 宣告一個返回值為
Collection<>
的公共靜態方法,並使用@Parameters
進行修飾 - 為測試類宣告一個帶有引數的公共建構函式,並在其中為之宣告變數賦值
- 編寫測試方法,使用變數
演示程式碼:
package com.imooc.util;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class ParameterTest {
/*
* 1.更改預設的測試執行器為RunWith(Parameterized.class)
* 2.宣告變數來存放預期值 和結果值
* 3.宣告一個返回值 為Collection的公共靜態方法,並使用@Parameters進行修飾
* 4.為測試類宣告一個帶有引數的公共建構函式,並在其中為之宣告變數賦值
*/
int expected = 0;//預期值
int input1 = 0;//輸入值1
int input2 = 0;//輸入值2
@Parameters //可以將返回的引數依次放入構造方法中進行測試
public static Collection<Object[]> t() {
return Arrays.asList(new Object[][]{
{3,1,2},//預期值,輸入值1,輸入值2
{4,2,2}
}) ;
}
public ParameterTest(int expected,int input1,int input2) {
this.expected = expected;
this.input1 = input1;
this.input2 = input2;
}
@Test
public void testAdd() {
assertEquals(expected, new Calculate().add(input1, input2));
}
}
在 Spring 中進行測試
Spring 配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>
<bean id="date" class="java.util.Date"/>
</beans>
Spring 測試程式碼
package com.imooc.conform;
import java.util.Date;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
private static ApplicationContext context = null;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
context = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void test() {
Date date = (Date) context.getBean("date");
System.out.println(date);
}
}