開發中經常用到單元測試,但有的邏輯代碼涉及到數據庫操作,當然,在測試的時候可以連接數據庫測試,但有一些特殊情況是不能讓工程編譯的時候連接數據庫的,這個時候單元測試就會出問題。於是,在不是主要測試數據庫的邏輯單元測試的時候,就可以用單元測試中的Mock功能來模擬數據,從而測試邏輯代碼結構是否完整,是否可以用某些特定的參數得到相應的結果。
簡單的說就是:通過模擬數據進行各類的單元測試
go
首先構建一個bean,這就是我們接下來要操作的數據了:
public class DemoData {
private String dataName;
private String dataInfo;
public String getDataName() {
return dataName;
}
public void setDataName(String dataName) {
this.dataName = dataName;
}
public String getDataInfo() {
return dataInfo;
}
public void setDataInfo(String dataInfo) {
this.dataInfo = dataInfo;
}
}
其次,是操作這個數據源的數據庫連接類(dao)
public interface DemoDataDao {
/**
* 通過傳入的值返回相應數量的數據集
* @param number 需要返回數據的數量
* @return 和傳入值相同數量的數據集
*/
List<DemoData> getSomeData(int number);
}
接下來是數據管理類接口(service)
public interface testService {
/**
* 獲取部分數據
* @param number 需要獲取的數據量
* @return 相應數據量的數據集
*/
List<DemoData> getSomeData(int number);
}
實現當前接口
@Component
public class TestServiceImpl implements testService {
@Autowired
private DemoDataDao demoDataDao;
@Override
public List<DemoData> getSomeData(int number){
return demoDataDao.getSomeData(number);
}
}
最後是控制類(Controller)
@RestController
@RequestMapping("/demo")
@EnableAutoConfiguration
public class TestController {
@Autowired
private testService service;
private static Integer flagNumber = 5;
@RequestMapping(value = "/test",method = RequestMethod.POST)
public List<DemoData> test(@RequestBody int number){
if(number > flagNumber){
return null;
}else{
return service.getSomeData(number);
}
}
}
好了,背景交代完畢,接下來開始構建測試類
===============================這=是=一=條=分=割=線=================================
首先,在工程的pom文件中添加對於mock數據的依賴
<!-- testNG測試類和Mock依賴 -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
對於某個類的測試類生成,
IDEA的快捷鍵是 ctrl+shift+t --> create new test
選擇JUnit4 並 勾上你要測試的方法 確定之後就會在當前工程目錄下創建出一個test類
首先 @InjectMocks算是聲明出要進行模擬數據的測試類,@Mock 就是聲明當前測試類中需要模擬數據的接口。舉例,就像我們現在用到的這個例子,在TestController中有用到testService這個接口的數據,那麼就@Mock出這個接口,如果在這個Controller中用到了其他的service,就mock出其他的service就行了
/**
* 構建測試對象
*/
@InjectMocks
private TestController controller;
/**
* Mock出數據構建類
*/
@Mock
private testService service;
以下爲整個測試類的完整代碼,具體操作意義見註釋
public class TestControllerTest {
/**
* 構建測試對象
*/
@InjectMocks
private TestController controller;
/**
* Mock出數據構建類
*/
@Mock
private testService service;
@BeforeClass
public void setUp() {
MockitoAnnotations.initMocks(this);
}
/**
* 構建初始化參數
*/
Integer number = 1;
@BeforeMethod
public void createData() {
number = 1;
}
@Test
public void testTest1() {
//當service中的getSomeData的參數爲1的時候,則返回getData方法參數爲1的數據
when(service.getSomeData(1)).thenReturn(getData(1));
//開始測試controller中的test方法,並返回結果
List<DemoData> list = controller.test(number);
//構建期望值(也就是告訴程序結果應該是個什麼樣子)
List<DemoData> list1 = getData(1);
//給當前測試下斷言(結果值與期望值對比)
Assert.assertEquals(list.size(),list1.size());
}
/**
* 構建模型數據
* @param number 需要返回的數據條數
* @return 返回相應條數的數據
*/
private List<DemoData> getData(Integer number){
List<DemoData> list = new ArrayList<>();
for(int run=0;run<number;run++){
DemoData data = new DemoData();
data.setDataName("name"+run);
data.setDataInfo("info"+run);
list.add(data);
}
return list;
}
}
點擊測試:
結果如下:
測試成功