1、什么是Junit4
JUnit4是一個易學(xué)易用的Java單元測試框架,一般我們在寫完一段代碼或一個方的時候,都要測試一下這段代碼和這個方法的邏輯是不是正確,輸入一定的數(shù)據(jù),返回的數(shù)據(jù)是不是我們想要的結(jié)果,即我們在寫單個業(yè)務(wù)代碼針對結(jié)果進行測試。這時Junit就派上了大用場了。
2、為何使用Junit4
也許有的初學(xué)者會說,項目完成之后測試不行嗎?如果你要這么想的話,那就了,因為隨著你代碼的增加,你牽扯到的模塊和項目中的邏輯就會越來越多,這樣測試起來就會非常的麻煩,而且容易出錯。Junit看起來是增加了代碼量,可是它可以大大的減少后期的測試時間,提升代碼的質(zhì)量,讓代碼更易于維護。
3、Junit4的快速入門
下載并導(dǎo)入Junitjar包:
首先得需要去網(wǎng)上下載一個Junit4的一個jar包,保存到自己本地電腦里面打開myEclipse新建一個Java項目,通過右擊項目-->Build Path --->Configure Build Path -->Add External JARs--->找到自己剛保存的jar路徑,點擊OK就可以啦
創(chuàng)建測試目錄:
接下來就要為我們的測試建立特殊的路徑,這個特殊特殊在哪里呢,因為我們的測試代碼要單獨保存不能與源代碼進行混淆,到項目結(jié)束后可以直接把它刪除,而且不會對項目造成影響。怎么創(chuàng)建呢:右擊項目名稱--->new---->suorce folder--->輸入你想要的測試文件名點擊OK就可以啦。
接下來我們得在項目中的src目錄下創(chuàng)建一個包,注意這兒的包名和test里面的包名要保持一致,在我們src的包下寫我們項目的邏輯方法,在test的報下寫我們的測試方法,結(jié)構(gòu)如圖所示,

下面我們來寫一段簡單的邏輯代碼進行測試演練
package com.junit;
public class method_junti {
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 division(int a, int b) {
return a / b;
}
}
方法很簡單,就是一般的加減乘除,下面我們就可以進行測試了,怎么測試呢: 在我們的測試目錄下新建測試類junit_test,然后定義測試方法。代碼如下:
package com.junit;
import static org.junit.Assert.*;
import org.junit.Test;
public class junit_test {
//測試方法必須有@test;
//該測試方法必須由public void修飾,沒有返回值;
//該方法不帶任何參數(shù);
//新建一個源代碼測試文件單獨存放測試代碼;
//測試類的包和被測試類的包保持一致;
//測試方法間互相獨立沒有任何依賴;
@Test
public void testAdd(){
assertEquals(4, new method_junti().add(3, 0));
}
@Test
public void testSubtract(){
assertEquals(3, new method_junti().subtract(6, 3));
}
@Test
public void testMultiply(){
assertEquals(6, new method_junti().multiply(6, 1));
}
@Test
public void testDivision(){
assertEquals(6, new method_junti().division(6, 1));
}
}
下面來講解一下assertEquals()這個函數(shù),它的第一個參數(shù)是你預(yù)期的一個結(jié)果,第二個參數(shù)使我們想測試的函數(shù),這個函數(shù)我們要通過先new出函數(shù)所在的類,然后通過類來調(diào)用方法,方法里面的參數(shù)就是你在寫該方法是傳進來的參數(shù)。在這里最好在你需要測試的方法的前面加上test,這樣的話就會比較規(guī)范一些
寫完之后你可以點擊測試類,然后在點擊run as,再點擊Junit test,你就能在彈出的窗口中看到你的測試結(jié)果,它會提示你失敗的個數(shù)和錯誤的個數(shù)。如果你只想測試一個方法怎么辦呢,在你創(chuàng)建的測試類的下面還有目錄,列表里面的會列出你所有的測試方法,你就可以右擊你想測試的方法,然后run as ---> junit test,測試成功后就會看到一個綠色的條,結(jié)果如圖:

在這里如果我們每一個方法都要自己手動的敲出它的測試方法,在這里我們只是簡單的測試了幾個方法,在項目中如果我們有很多的方法需要測試,一個一個的敲的話會有些浪費時間了,這里給大家介紹一個快速生成測試方法的一個方法:
點擊src下的method_junit.java--->右擊new--->看看后面的提示框中有么有Junit test case,如果沒有的話點擊other,在提示框中輸入Junit 就會出現(xiàn)--->在彈出的對話框中找到Source folder,點擊后面的Browse將其改為含有test的那個目錄,這里有些可能會提示名字重復(fù),把下面的 Name改改就行--->點擊next--->你會看到method_junit里面的所有法,這時候你就可以選中它們,成成測試方法如下:
package com.junit;
import static org.junit.Assert.*;
import org.junit.Test;
public class method_juntiTest2 {
@Test
public void testAdd() {
fail("Not yet implemented");
}
@Test
public void testSubtract() {
fail("Not yet implemented");
}
@Test
public void testMultiply() {
fail("Not yet implemented");
}
@Test
public void testDivision() {
fail("Not yet implemented");
}
}
再把里面fail后面的語句刪了就可以寫你想測試的東西呢!
4、junit測試失敗的兩種情況:
在前面的情況中我們都是測試的是成功的例子,但是Junit的作用只是測試的方法里的返回數(shù)據(jù)是不是正確的,但是在數(shù)據(jù)返回正確的情況下我們未必是正確的,就比如如果你要求的是長方形的面積,但是你用的是周長公式,當你在測試的時候他也會給你測試成功,得到預(yù)期的結(jié)果,也就是說我們的測試用例對于邏輯錯誤是無能為力的
測試失敗的情況一
當我們預(yù)期值和程序執(zhí)行的結(jié)果不一樣的時候就會測試失?。?br>
比如我們上面的測試加法函數(shù)的方法:
@Test
public void testAdd(){
assertEquals(3, new method_junti().add(3, 0));
}
如果把預(yù)期結(jié)果3,改為4,就會測試失敗,failure的后面就會出現(xiàn)一個1,提示一個測試失敗,運行時就能看到,這個應(yīng)該不難理解。如果你仔細觀察的話,下面還會有相關(guān)的提示,如圖所示:

測試失敗情況二:
下面我們在來測試除法:
@Test
public void testDivision(){
assertEquals(6, new method_junti().division(6, 1));
}
如果在這里把除數(shù)改為0,會出現(xiàn)什么情況呢:后面的提示框中的error數(shù)就會變1;提示有一個錯誤。于是我們得出下面的兩種情況:
1、failure一般由單元測試使用的斷言方法判斷失敗所引起的,這表示測試點發(fā)現(xiàn)了問題,也就是說程序輸出的結(jié)果和預(yù)期的不一樣
2、error是由代碼異常引起的,他可能是由于測試代碼本身的錯誤,也可能是被測試代碼中隱藏的一個bug
5、Junit的運行流程:
首先我們先在test包下的com.junit新建一個junit case,和并且直接命名junit_case。在創(chuàng)建的時候把setUpBeforeClass(),tearDownAfterClass(),setUp() ,tearDown() 選上就會得到下面的代碼:
package com.junit;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class Junit_case {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void test() {
fail("Not yet implemented");
}
}
下面我們在每個方法中輸入一句簡單的輸出語句,看看他們的運行狀態(tài),如下:
package com.junit;
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 Junit_test1 {
/* 1、BeforeClass修飾的方法會在所有方法被調(diào)用前執(zhí)行
* 而且該方法是靜態(tài)的,所以當測試類被加載后接著就執(zhí)行它
* 在內(nèi)存中它只會存在一份,適合加載配置文件
* 2、AfterClass修飾的方法用來對資源的清理,如關(guān)閉數(shù)據(jù)庫的連接
* befoer和after修飾的方法在每個test修飾的方法執(zhí)行前會被各執(zhí)行一次,假如有兩個
* test文件,before和after會被各執(zhí)行兩次;
* */
@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");
}
}
如果運行上面的代碼,就會得到下面的結(jié)果
6、junit的常用注解:
上面我已經(jīng)講解了@test,@BeforeClass,@AfterClass,@Before,@After這些注解的詳解可見這位仁兄的博客,下面提供相關(guān)地址:http://blog.csdn.net/zixiao217/article/details/52951679
對于@test,他除了將一個普通的方法修飾為測試方法外,還可以處理異常,設(shè)置超時。下面來對test的異常處理做講解test有兩個參數(shù):expected和timeout,即異常處理和設(shè)置超時如果對我們上面的除數(shù)為0的那個方法進行異常處理,那么我們就可以看到代碼能夠正常,測試通過,代碼如下:
@Test(expected=ArithmeticException.class)
public void testDivision(){
assertEquals(6, new method_junti().division(6, 0));
}
在測試一些對性能有要求的方法中設(shè)置超時是很有必要的,它可以檢測你的代碼能否在這個
時間段內(nèi)運行出結(jié)果,設(shè)置方法如下:
@Test(timeout=2000)//單位是毫秒
public void testWhile(){
while(true){
System.out.println("run forever");
}
}
@Ignore:在test方法上加上該修飾,測試的時候就會不執(zhí)行該測試方法;
@RunWith可以更改測試運行器;我們除了使用junit提供的測試運行器之外,還可以自定義
我們的運行器,只要繼承org.junit.runner.Runner
代碼如下:
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@Suite.SuiteClasses({TaskTest1.class,TaskTest2.class,TaskTest3.class})
public class SuitTest {
public void test(){
/*
* 由于在開發(fā)的項目中,測試的類很多,一個一個運行很浪費時間,于是可以寫一個測試
* 套件把所有需要測試的類組合在一起測試運行
* 1、寫一個測試入口,這個類不含其它的方法;
* 2、更改測試運行器@RunWith(Suite.class)
* 3、將要測試的類作為數(shù)組放在@Suite.SuiteClasses({})中;
*/
}
}
7、junit的參數(shù)設(shè)置
在上面的測試中,我們對一個方法都是只測試了一組數(shù)據(jù),可是在真正的項目中,一組數(shù)據(jù)往往是不夠的,我們需要很多組數(shù)據(jù),如果每一組數(shù)組寫一個測試方法的話那可把我們的工作人員累死了!這時我們可以使用參數(shù)設(shè)置來解決這個問題。
代碼如下:
package com.junit;
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 {
//聲明變量存放預(yù)期值和測試數(shù)據(jù);
int expected=0;
int input1=0;
int input2=0;
@Parameters
public static Collection<Object[]> test(){
return Arrays.asList(new Object[][]{
{3,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 method_junti().add(input1, input2));
}
}
我們需要測試多組數(shù)據(jù),那么我們就需要用到數(shù)組來存放多組數(shù)據(jù),這里用Arrays.asList來接收。