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