JAVA 單元測試總結
單元測試的重要性這裡就不說了,直接進入正題。很多程式設計師不喜歡寫單元測試,導致專案經常會花很多時間去debug,這完全得不償失。對關鍵方法進行單元測試,可以在早期業務邏輯還沒那麼複雜的時候,儘快排除癥結。
在dao,manager,server,web這樣的分層專案中,通常單元測試是要寫在server層的,因為server層可以測的最多。本文中不介紹單元測試的原理,只是介紹單元測試最常用的斷言和Jmockit的用法,可以應付業務開發中絕大部分單元測試。
首先新增maven依賴
<dependencie>
<dependency>
<groupId >junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId >
<version>3.2.9.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.24</version>
<scope >test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.4</version>
<scope>test</scope>
</dependency>
</dependencie>
1 BaseTest.java
server層新建test包,在IDEA中標記為綠色,這個裡面寫Before和After,如果不需要,就空在這裡即可。其它具體的測試類要繼承BaseTest.java。
package com.sf.sfpp.notice.test;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/test-service.xml" })
public class BaseTest extends AbstractTransactionalJUnit4SpringContextTests {
@Before
public void init(){
}
@After
public void print(){
}
}
2 assert斷言
使用assert斷言是常用的單元測試方法之一。其本質是將方法的返回結果與預期值進行比較,相等則結果為綠色(單元測試通過),反之為紅色(單元測試未通過)。
比方說,我們在Manager層有一個類,UserHistoryManager,裡面有個方法是根據ID刪除使用者操作歷史
@Autowired
private UserHistoryMapper userHistoryMapper;
public int deleteUserHistoryById(int userHistoryId){
return userHistoryMapper.deleteUserHistoryById(userHistoryId);
}
現在想要對這個方法進行單元測試,在server層的test下面的impl資料夾中新建一個TestUserHistoryManager類,依舊如第一張圖所示,程式碼如下:
package com.sf.sfpp.notice.test.impl;
import com.sf.sfpp.notice.common.domain.UserHistory;
import com.sf.sfpp.notice.manager.UserHistoryManager;
import com.sf.sfpp.notice.test.BaseTest;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
public class TestUserHistoryManager extends BaseTest {
@Autowired
private UserHistoryManager userHistoryManager;
@Test
public void testDeleteUserHistoryById(){
Assert.assertEquals(true,userHistoryManager.deleteUserHistoryById(4) > 0);
}
}
3 Jmockit
有些方法要遠遠比上面的assert複雜,例如當你的方法中要新增一個物件到資料庫中,此時如何進行單元測試呢?
還是如第一張圖片所示,在test下面的impl資料夾中新建TestUserNotificationManager.java,測試一下UserHistoryManager中新增使用者歷史的方法。
package com.sf.sfpp.notice.test.impl;
import com.sf.sfpp.notice.common.domain.UserHistory;
import com.sf.sfpp.notice.manager.UserHistoryManager;
import com.sf.sfpp.notice.test.BaseTest;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class TestUserNotificationManager extends BaseTest {
@Autowired
private UserHistoryManager userHistoryManager;
@Test
public void testAddUserHistory(){
UserHistory userHistory = mock(UserHistory.class);
when(userHistory.getAction()).thenReturn("balabala");
when(userHistory.getTargetId()).thenReturn("balabala");
when(userHistory.getUserId()).thenReturn(43);
when(userHistory.getTargetKind()).thenReturn("balabala");
when(userHistory.getId()).thenReturn("balabala");
Assert.assertTrue(userHistoryManager.addUserHistory(balabala));
}
}
上面的方法相當於用Jmockit虛擬了一個UserHistory物件(使用者操作歷史),然後根據其中的每個屬性看返回值(字串屬性對應字串返回值,int屬性對應int返回值)。
在IDEA中點選方法名前面的綠色箭頭(ctrl+shift+F10)
單元測試只要看到下面的綠色條,就表示測試通過了。