Junit4 單元測試框架的常用方法介紹


Junit 介紹:

Junit是一套框架(用於JAVA語言),由 Erich Gamma 和 Kent Beck 編寫的一個回歸測試框架(regression testing framework),即用於白盒測試。

 

本文介紹的內容:

1 Junit Myeclipse測試類的生成

JUnit 4 常用的幾個annotation 介紹與使用 (@Before  @After @Test @Ignore @BeforeClass @AfterClass)

3 常用的斷言介紹

4 特殊的處理 (限時測試,異常測試)

5 參數化配置 (@Parameters)

 

准備測試代碼

測試的方法(正確、錯誤方法、死循環、拋異常)

LogicService 
package com.logic;

public class LogicService {
    
    public int add(int x ,int y){ //加法
        return x+y;
    }
    
    public int sub(int x ,int y){ //減法
        return x-y;
    }
    
    public int div(int x ,int y){ //除法 
        return x/y;
    }
    
    public int div2(int x ,int y){ //除法  做了異常判斷
        try {
            int z = x/y;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return x/y;
    }
    
    public void loop(int x ,int y){ //死循環
        for(;;)
            x=y;
    }    
    
    public void unCompleted(int x ,int y){ //未完成的模塊
        //還在開發中
    }
    
}

 

一  Myeclipse測試類的生成

1 對需要測試的類點右鍵 NEW 一個Junit Test Case

 

 

2 點擊NEXT

 注意 1 選擇NEW Junit 4 test

        2 source folder 是默認會填寫上之前右鍵NEW的那個類,如果不是的話,請自行進行修改

        3 package 默認會填寫當前的包名 個人建議重新開個測試包-即在包后面加上.test 表示是單元測試用例專用包與源代碼分離

        4 name 默認會在之前右鍵NEW的那個類的基礎的后面加上Test 如果不是的話,建議自行進行修改,便於標示

        5 初始化的方法,我一般會勾上個setUp,這個請隨意。

        

3 繼續點擊NEXT

1 這里可以選擇需要測試的方法,我一般都是全選的然后在生成的測試類中再做處理

2 點擊finish完成

 

4 生成的單元測試類

package com.logic.test;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

public class LogicServiceTest {

    @Before
    public void setUp() throws Exception {
    }

    @Test
    public void testAdd() {
        fail("Not yet implemented");
    }

    @Test
    public void testSub() {
        fail("Not yet implemented");
    }

    @Test
    public void testDiv() {
        fail("Not yet implemented");
    }

    @Test
    public void testDiv2() {
        fail("Not yet implemented");
    }

    @Test
    public void testLoop() {
        fail("Not yet implemented");
    }

    @Test
    public void testUnCompleted() {
        fail("Not yet implemented");
    }

}

 

二 JUnit 4 常用的幾個annotation 介紹與使用 (@Before  @After @Test @Ignore @BeforeClass @AfterClass)

1 常用的annotation介紹

 @Before:初始化方法,在任何一個測試執行之前必須執行的代碼; 

 @After:釋放資源,在任何測試執行之后需要進行的收尾工作。在每個測試方法執行之后執行一次,該annotation只能修飾public void 方法;

 @Test:測試方法,表明這是一個測試方法。在Junit中將會自動被執行。該annotation只你呢個修飾public void 方法

 @Ignore:忽略的測試方法,標注的含義就是“某些方法尚未完成,暫不參與此次測試”;

 @BeforeClass:針對所有測試,只執行一次,且必須為public static void;一般用於初始化必要的消耗較大的資源,例如數據庫連接等

 @AfterClass:針對所有測試,將會在所有測試方法執行結束后執行一次,且必須為public static void; 

 

2 常用的annotation測試

 修改單元測試類LogicServiceTest

package com.logic.test;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

public class LogicServiceTest {

    @Before
    public void setUp() throws Exception {
        System.out.println("@Before");//測試@Before
    }

    @After
    public void end() throws Exception {
        System.out.println("@After");//測試@@After
    }

    @BeforeClass
    public static void init() throws Exception {
        System.out.println("@BeforeClass");//測試@BeforeClass
    }

    @AfterClass
    public static void disstroy() throws Exception {
        System.out.println("@AfterClass");//測試@AfterClass
    }

    @Test
    public void testAdd() {
        System.out.println("@Test testAdd");//測試@Test
    }

    @Test
    public void testSub() {
        System.out.println("@Test testSub");//測試@Test
    }

    @Ignore
    public void testDiv() {
        System.out.println("@Ignore ");//測試@Ignore
    }

    @Ignore
    public void testDiv2() {
        System.out.println("@Ignore ");//測試@Ignore
    }

    @Ignore
    public void testLoop() {
        System.out.println("@Ignore ");//測試@Ignore
    }

    
    public void testUnCompleted() {
        System.out.println("@Ignore ");//測試未標注
    }

}

 

執行結果

執行結果分析

1 @BeforeClass和@AfterClass只執行一次,在所有方法開始前/后

2 @Before和@After在每個@Test標注的方法前后各執行一次

3 @Test 標注的方法都會執行一次(表示要測試的方法)

4 @Ignore方法不會被執行,沒有annotation的方法也不會被執行

5 總結  @BeforeClass –> (@Before –> @Test –> @After) –> @AfterClass

 

理解了以上注解后就可以嘗試着在日常的項目中使用Junit進行單元測試了。

 

3 常用的斷言介紹

assertEquals(String msg, Object expectRes, Object Res) --------  用於值判斷

判斷expectRes.equals(Res) ,表示值等於的判斷,失敗則拋MSG

assertSame(String msg, Object expectRes, Object Res)  --------  用於地址判斷

判斷expectRes==Res,表示地址等於的判斷,失敗則拋MSG

assertTrue(String msg,Boolean result) ----------------------------用於Boolean判斷

判斷result是true還是false,失敗則拋MSG

assertNull(String msg,Object result)-------------------------------用於NULL判斷

判斷result是否為NULL,失敗則拋MSG

fail(String msg);---------------------------------------------------直接中止方法運行

直接中止方法運行,拋出MSG

 

測試代碼

package com.logic.test;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

import com.logic.LogicService;

public class LogicServiceTest {
    LogicService logserv ;

    @Before
    public void setUp() throws Exception {
        logserv = new LogicService();
    }

    @Test
    public void testAdd() {
        String a = "aa";
        String t = "a";
        String b = "a"+t;
        assertEquals("assertEquals", a, b) ; //A與B的關系是值相等,地址不相等,這個用例會成功
    }

    @Test
    public void testSub() {
        String a = "aa";
        String t = "a";
        String b = "a"+t;
        assertSame("assertSame", a, b) ; //A與B的關系是值相等,地址不相等,這個用例會失敗
    }

    @Test
    public void testDiv() {
        assertTrue("assertTrue",true);//用例成功
        assertTrue("第二個為false失敗",false);//用例失敗
    }

    @Test
    public void testDiv2() {
        assertNull("assertNull",null);//用例成功
        assertNull("第二個為notNull失敗","a");//用例失敗
    }

    @Ignore
    public void testLoop() {
    }

    @Ignore
    public void testUnCompleted() {
    }

}

 

執行結果分析

這里我不再截圖了

1 成功

2 失敗,返回MSG為assertSame

3 第一個成功,第二個失敗,返回MSG為第二個為false失敗

4 第一個成功,第二個失敗,返回MSG為第二個為notNull失敗

斷言是用來判斷被測方法執行的結果與預期結果是否匹配

 

4 特殊的處理 (限時測試,異常測試)

1 Junit提供限時處理的機制。

@Test(timeout=1000) 單位毫秒

當方法用時超過1000毫秒時,此方法會自動中止並執行失敗

package com.logic.test;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

import com.logic.LogicService;

public class LogicServiceTest {
    LogicService logserv ;

    @Before
    public void setUp() throws Exception {
        logserv = new LogicService();
    }

    @Ignore
    public void testAdd() {
    }

    @Ignore
    public void testSub() {
    }

    @Ignore
    public void testDiv() {
    }

    @Test(timeout=1000) 
    public void testDiv2() {
        System.out.print("我不會超過1000毫秒的");
    }

    @Test(timeout=1000) 
    public void testLoop() {
        logserv.loop(1, 1);//此方法使用的是死循環實現,所以一定會超過限時,超過限時后此方法會自動中止
    }

    @Ignore
    public void testUnCompleted() {
    }

}

執行結果

loop方法超時報錯,div2方法不超時成功

 

2 Junit提供異常處理的機制。

@Test(expected=Exception.class) 其中Exception.class可以寫的更加具體

測試

    @Test(expected=Exception.class)
    public void testDiv() {
        System.out.print(logserv.div(3, 0));
    }

    @Test(expected=Exception.class)
    public void testDiv2() {
        System.out.print(logserv.div(3, 0));
    }

執行結果

兩個都通過

 

測試

    @Test(expected=Exception.class)
    public void testDiv() {
        System.out.print(logserv.div(3, 0));
    }

    @Test
    public void testDiv2() {
        System.out.print(logserv.div(3, 0));
    }

執行結果

第一個通過 第二個不通過 異常為除數不能為zero

 

5 參數化配置 (@Parameters)   重要

進行單元測試的時候,通常一個方法需要好幾個case進行測試,Junit提供參數化便於我們對方法進行多種參數的組合測試

如果不使用參數化進行測試的話,那么我們的測試類會做的很臃腫

例如

    @Test
    public void testAdd() {
        assertEquals("1+1 失敗",2,logserv.add(1, 1) );
    }
    @Test
    public void testAdd1() {
        assertEquals("1+2 失敗",3,logserv.add(1, 2) );
    }
    @Test
    public void testAdd2() {
        assertEquals("1+3 失敗",3,logserv.add(1, 3) );
    }
    @Test
    public void testAdd3() {
        assertEquals("1+4 失敗",3,logserv.add(1, 4) );
    }

這樣的測試類顯然看起來不是很理想,代碼過於重復

 

參數化的實現過程(重要)

1 在測試類上增加

@RunWith(Parameterized.class)並引入

import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

2 寫上構造類的函數及定義入參

例如

@RunWith(Parameterized.class)
public class LogicServiceTest {
    LogicService logserv ;
    int parm1 ;//定義入參
    int parm2 ;//定義入參
    int res;//定義入參
    
   public LogicServiceTest(int parm1,int parm2,int res){//定義構造函數
       this.parm1=parm1;
       this.parm2=parm2;
       this.res=res;
   }

3 定義一個返回結果為collection類型的方法並寫上@Parameters 

注意 Arrays.asList()里面NEW的Object的要與定義的參數一一對應

例如

public class LogicServiceTest {
    LogicService logserv ;
    int parm1 ;//定義入參
    int parm2 ;//定義入參
    int res;//定義入參
    
   public LogicServiceTest(int parm1,int parm2,int res){//定義構造函數
       this.parm1=parm1;
       this.parm2=parm2;
       this.res=res;
   }
   
   @Parameters   
   public static Collection<Object[]> initParm(){
       return  Arrays.asList(new Object[][]{
          {1,1,2},{1,2,3},{1,3,4},{1,3,5}//{}里的參數一定要和構造函數一一對應
   });
   }

4 編寫測試方法,調用參數

    @Test
    public void testAdd() {
        assertEquals(res,logserv.add(parm1, parm2));
    }

5 測試類代碼全景(准備執行)

package com.logic.test;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import com.logic.LogicService;

@RunWith(Parameterized.class)
public class LogicServiceTest {
    LogicService logserv;
    int parm1;// 定義入參
    int parm2;// 定義入參
    int res;// 定義入參

    public LogicServiceTest(int parm1, int parm2, int res) {// 定義構造函數
        this.parm1 = parm1;
        this.parm2 = parm2;
        this.res = res;
    }

    @Parameters
    public static Collection<Object[]> initParm() {
        return Arrays.asList(new Object[][] { { 1, 1, 2 }, { 1, 2, 3 },
                { 1, 3, 4 }, { 1, 3, 5 } // {}里的參數一定要和構造函數一一對應
                });
    }

    @Before
    public void setUp() throws Exception {
        logserv = new LogicService();
    }

    @Test
    public void testAdd() {
        assertEquals(res, logserv.add(parm1, parm2));
    }

    @Ignore
    public void testSub() {
    }
}

6 執行結果

總結:使用了參數化后測試類的代碼簡化了不少,而且執行起來效果很不錯

 

收尾

通過本文可以了解到:

1 Junit Myeclipse測試類的生成

2 JUnit 4 常用的幾個annotation 介紹與使用 (@Before  @After @Test @Ignore @BeforeClass @AfterClass)

3 常用的斷言介紹

4 特殊的處理 (限時測試,異常測試)

5 參數化配置 (@Parameters)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM