單元測(cè)試第三彈——使用JUnit進(jìn)行單元測(cè)試
上一彈中介紹了單元測(cè)試以及單元測(cè)試框架,這一彈主要來介紹一下JUnit這個(gè)目前比較流行的單測(cè)框架。
JUnit是由 Erich Gamma 和 Kent Beck 編寫的一個(gè)回歸測(cè)試框架(regression testing framework)。Junit測(cè)試是程序員測(cè)試,即所謂白盒測(cè)試,因?yàn)槌绦騿T知道被測(cè)試的軟件如何(How)完成功能和完成什么樣(What)的功能。Junit是一套框架,繼承TestCase類,就可以用Junit進(jìn)行自動(dòng)測(cè)試了。
現(xiàn)在很多IDE中都已經(jīng)集成了JUnit,當(dāng)我們?cè)趧?chuàng)建maven項(xiàng)目的時(shí)候,一般在pom文件中也會(huì)自動(dòng)增加junit的依賴。
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- <version>4.4</version>
- </dependency>
注意上面的maven的依賴中的scope,因?yàn)閖unit只在測(cè)試代碼中會(huì)被用到,這里scope指定未test即可。我們直接使用和介紹JUnit4。
上手JUnit
要測(cè)試,要先有被測(cè)代碼(當(dāng)然,基于測(cè)試編程可以先有測(cè)試代碼)。先來看我們想要測(cè)試的代碼:
- public class CaculateService {
- public float divide(float divisor, float dividend) {
- return divisor / dividend;
- }
- }
我們想要測(cè)試這個(gè)類,那么如何使用Junit進(jìn)行測(cè)試呢?先來寫一個(gè)測(cè)試類。如果你使用的是IntelliJ+Mac,那么可以在類名上使用快捷鍵option+enter直接生成測(cè)試類,這樣IDE會(huì)幫忙生成一個(gè)對(duì)應(yīng)的測(cè)試類。(其他操作系統(tǒng)和IDE也有同樣的功能)
生成后的測(cè)試代碼和被測(cè)代碼所處路徑如下:
可以看到,一般的maven項(xiàng)目中,會(huì)在src/main下面有兩個(gè)目錄,java和test,java目錄中放的是源碼,test目錄中放的是測(cè)試代碼。測(cè)試代碼和測(cè)試代碼的包名保持一致即可。
測(cè)試代碼如下:
- public class CaculateServiceTest {
- CaculateService caculateService = new CaculateService();
- @Test
- public void testDivide() throws Exception {
- Assert.assertEquals(caculateService.divide(2, 1), 2.0);
- }
- }
然后執(zhí)行該方法就可以了,先不管Assert.assertEquals的用法及結(jié)果,這里總結(jié)下使用JUnit寫測(cè)試代碼的簡單步驟:
- 創(chuàng)建一個(gè)名為 CaculateServiceTest.java 的測(cè)試類。
- 向測(cè)試類中添加名為 testDivide() 的方法。
- 向方法中添加 Annotaion @Test。
- 執(zhí)行測(cè)試條件并且應(yīng)用 Junit 的 assertEquals API 來檢查。
JUnit中的Assert
- public class Assert extends java.lang.Object
- 這個(gè)類提供了一系列的編寫測(cè)試的有用的聲明方法。只有失敗的聲明方法才會(huì)被記錄。
- void assertEquals(boolean expected, boolean actual)
- 檢查兩個(gè)變量或者等式是否平衡
- void assertFalse(boolean condition)
- 檢查條件是假的
- void assertNotNull(Object object)
- 檢查對(duì)象不是空的
- void assertNull(Object object)
- 檢查對(duì)象是空的
- void assertTrue(boolean condition)
- 檢查條件為真
- void fail()
- 在沒有報(bào)告的情況下使測(cè)試不通過
這些方法我就不一一介紹了,相信我的讀者們都能看懂并在平時(shí)開發(fā)中用的到,還是比較容易理解的。
Assert可以用來判斷方法的真是結(jié)果和預(yù)期結(jié)果是否一樣。是我們?cè)趯憜卧獪y(cè)試中用到最多的一個(gè)api。
JUnit中的注解
- @BeforeClass:針對(duì)所有測(cè)試,只執(zhí)行一次,且必須為static void
- @Before:初始化方法
- @Test:測(cè)試方法,在這里可以測(cè)試期望異常和超時(shí)時(shí)間
- @After:釋放資源
- @AfterClass:針對(duì)所有測(cè)試,只執(zhí)行一次,且必須為static void
- @Ignore:忽略的測(cè)試方法
一個(gè)單元測(cè)試類執(zhí)行順序?yàn)椋?/p>
@BeforeClass –> @Before –> @Test –> @After –> @AfterClass
每一個(gè)測(cè)試方法的調(diào)用順序?yàn)椋?/p>
@Before –> @Test –> @After
時(shí)間測(cè)試
如果一個(gè)測(cè)試用例比起指定的毫秒數(shù)花費(fèi)了更多的時(shí)間,那么 Junit 將自動(dòng)將它標(biāo)記為失敗。timeout 參數(shù)和 @Test 注釋一起使用?,F(xiàn)在讓我們看看活動(dòng)中的 @test(timeout)。
- @Test(timeout = 1000)
- public void testTimeoutSuccess() {
- // do nothing
- }
異常測(cè)試
你可以測(cè)試代碼是否它拋出了想要得到的異常。expected 參數(shù)和 @Test 注釋一起使用?,F(xiàn)在讓我們看看活動(dòng)中的 @Test(expected)。
- @Test(expected = NullPointerException.class)
- public void testException() {
- throw new NullPointerException();
- }
所有測(cè)試代碼
- package com.hollischuang.effective.unitest.service;
- import org.junit.*;
- /**
- * @author Hollis 17/1/7.
- */
- public class JUnitTest {
- /**
- * 只執(zhí)行一次,在整個(gè)類執(zhí)行之前執(zhí)行
- */
- @BeforeClass
- public static void beforeClass() {
- System.out.println("in before class");
- }
- /**
- * 只執(zhí)行一次,在整個(gè)類執(zhí)行之后執(zhí)行
- */
- @AfterClass
- public static void afterClass() {
- System.out.println("in after class");
- }
- /**
- * 每個(gè)測(cè)試方法被執(zhí)行前都被執(zhí)行一次
- */
- @Before
- public void before() {
- System.out.println("in before");
- }
- /**
- * 每個(gè)測(cè)試方法被執(zhí)行后都被執(zhí)行一次
- */
- @After
- public void after() {
- System.out.println("in after");
- }
- // test case 1
- @Test
- public void testCase1() {
- System.out.println("in test case 1");
- }
- // test case 2
- @Test
- public void testCase2() {
- System.out.println("in test case 2");
- }
- /**
- * 測(cè)試assertEquals
- */
- @Test
- public void testEquals() {
- Assert.assertEquals(1 + 2, 3);
- }
- /**
- * 測(cè)試assertTrue
- */
- @Test
- public void testTrue() {
- Assert.assertTrue(1 + 2 == 3);
- }
- /**
- * 測(cè)試assertFalse
- */
- @Test
- public void testFals() {
- Assert.assertFalse(1 + 2 == 4);
- }
- /**
- * 測(cè)試assertNotNull
- */
- @Test
- public void assertNotNull() {
- Assert.assertNotNull("not null");
- }
- /**
- * 測(cè)試assertNull
- */
- @Test
- public void assertNull() {
- Assert.assertNull(null);
- }
- /**
- * 測(cè)試fail和Ignore
- */
- @Test
- @Ignore
- public void assertFail() {
- Assert.fail();
- }
- /**
- * 測(cè)試異常
- */
- @Test(expected = NullPointerException.class)
- public void testException() {
- throw new NullPointerException();
- }
- /**
- * 測(cè)試時(shí)間
- */
- @Test(timeout = 1000)
- public void testTimeoutSuccess() {
- // do nothing
- }
- /**
- * 測(cè)試時(shí)間
- */
- @Test(timeout = 1000)
- public void testTimeoutFailed() {
- while (true) {
- }
- }
- }
總結(jié)
本文主要介紹了JUnit的常見用法,后面會(huì)專門寫一篇文章介紹如何將JUnit和Spring集合到一起。
【本文是51CTO專欄作者Hollis的原創(chuàng)文章,作者微信公眾號(hào)Hollis(ID:hollischuang)】