本文是自己對學習的一個總結
1、基本Mockito測試的編寫
瞭解到什麼是Mockito,並且配置好Mockito的maven之後,我們就可以開始編寫一個最基本的Mockito測試類了。如果對這兩個內容不太瞭解,可以查看這篇文章https://blog.csdn.net/sinat_38393872/article/details/106520371。
1.1、確定項目結構
1.1.1、 業務代碼的結構
Mockito是在Spring的框架中使用的單元測試,我們先新建一個Spring的項目,項目結構如下所示。
這是一個典型的Spring項目結構,Service層是我們想要測試的類。Service的代碼依賴Dao層的類,我們將在測試中模擬dao層的代碼,不讓dao層的代碼真正執行。
我們先看看StudentServiceImpl的代碼
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
/**
* 這是準備測試的代碼,其中的studentDao.insert方法我們要模擬執行
*/
@Override
public boolean insert(Integer id) {
if(studentDao.insert(id) >= 1) {
return true;
} else {
return false;
}
}
}
我們再看看StudentServiceImpl依賴的StudentDao的代碼。
public class StudentDao {
public int insert(Integer id) {
System.out.println("執行了真正的操作");
return 1;
}
}
額·····這個代碼不是真正地操作數據庫,先別在意這個。總之,這段代碼真正執行的話,應該要在控制檯輸出"執行了真正的操作"這麼一行字,我們等會測試的時候查看控制檯有沒有輸入相應的內容就知道這段代碼有沒有被真正執行了。
1.1.2、測試代碼的項目結構
測試文檔的項目結構應該與業務代碼的一致。測試類和被測試類的相對位置應該是一樣的。同時,測試類的命名建議爲”被測試類+Test"。
比如上面的被測試類是StudentService,對應的測試類就是StudentServiceTest。StudentService的目錄是com.example.mokitoLearning.student.service.StudentService,StudentServiceTest的目錄也是com.example.mokitoLearning.student.service.StudentServiceTest。
除此之外,測試方法的命名也建議是“被測試方法 + Test”。比如我們測試StudentService中的insert方法,那我們的測試方法就應該寫在StudentServiceTest之下,方法名爲insertTest。
2、編寫測試類
2.1 標記被測試的類(@InjectMocks)
確定好項目結構以後,我們在測試類中開始寫測試方法。 測試類不會自己知道我們想測試哪個類,所以我們使用@InjectMocks標註一下。
public class StudentServiceTest {
@InjectMocks
private StudentServiceImpl studentService;
//其他操作
}
@InjectMocks標註的類型不能是接口,所以我標註的是StudentService的實現類。
2.2 給被測試類注入依賴(@Mock)
被測試類的依賴是需要注入的。我們使用@Mock進行注入。@Mock標記的變量會被注入到@InjectMocks標註的變量中。其用法和@Autowired一樣。
public class StudentServiceTest {
@InjectMocks
private StudentServiceImpl studentService;
@Mock
private StudentDao studentDao;
}
2.3 初始化Mockito(@Before和MockitoAnnotations.initMocks(this);)
測試方法執行前,必須先初始化Mockito。初始化Mockito是這樣的。
MockitoAnnotations.initMocks(this);
我們現在先別管這裏面做了什麼,只要知道測試方法執行前,必須先執行這一條語句。
這樣的話,每個方法的第一句我們就要先寫這麼一條語句,這有些麻煩。我們可以利用@Before註解讓程序簡潔一些。
@Before用來標註一個public void方法,這個被標註的方法會在所有的測試方法運行前運行。通常在@Before標註的方法中定義一些公共邏輯,比如初始化MockitoAnnotations.initMocks(this);就是其中之一。使用@Before後,我們就不用在每一個測試方法中都寫初始化Mockito的語句了。
public class StudentServiceTest {
@InjectMocks
private StudentServiceImpl studentService;
@Mock
private StudentDao studentDao;
/**
* 不用在意方法名是什麼,只要方法是public void的就可以
*/
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
}
另外,我們可以定義多個@Before標註的方法。
2.4 標記測試方法(@Test)
我們使用@Test標記一個方法是測試方法,標記以後這個方法纔可以被測試。項目啓動時,系統會運行@Test標註的方法,方法中出錯的話(邏輯不符合我們的預期),項目會無法啓動,這時候我們就能知道項目的代碼是有問題的。這樣就能幫助我們快速知道問題所在,也能提前知道項目存在問題,避免上線隱患。
public class StudentServiceTest {
@InjectMocks
private StudentServiceImpl studentService;
@Mock
private StudentDao studentDao;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void insertTest() {
//測試邏輯
}
}
2.5 模擬依賴
單元測試中,不能真正執行依賴的外部邏輯。我們必須模擬執行。
在Mockito中,我們可以使用
Mockito.when().thenReturn();
這樣的語句來模擬依賴邏輯。這個方法應該在測試方法的開始部分就寫明。這個方法表示測試邏輯運行時,到了要調用某一個方法的時候,不去執行這個方法,直接返回一個值。我們看看示例。
Mockito.when(studentDao.insert(Mockito.any())).thenReturn(3);
這個語句之後,我們測試執行studentDao的insert方法時,一遇到studentDao.insert()方法時,系統就不會去真正執行這個方法,而是模擬執行,直接返回3。我們還可以設置爲不返回值,而是拋出異常。更多的用法可以看官方文檔https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#34。
到了這裏我們就應該能寫出一個基本的測試了。
public class StudentServiceTest {
@InjectMocks
private StudentServiceImpl studentService;
@Mock
private StudentDao studentDao;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void insertTest() {
Mockito.when(studentDao.insert(Mockito.any())).thenReturn(3);
//執行到studentDao.insert方法是,直接返回3,那麼下面這條語句的斷言應該不會報錯
Assert.assertEquals(true, studentService.insert(1));
System.out.println(studentService.insert(4));
}
}
執行測試方法,輸出結果如下
沒有輸出"執行了真正的操作",所以studentDao.insert方法確實沒有真正執行,模擬成功。