[英]Mockito: how to verify method call of a singelton class from another singelton class
我是單元測試和Mockito的新手,如何為給定的代碼片段(單例)編寫測試代碼。
1.我想為XYZ類編寫單元測試。
2.我想驗證方法是否被調用。
3.我想編寫測試代碼以檢查temp變量的狀態。
4.我也想為專用方法計算器編寫測試代碼。
ABC類是單例,具有兩個字段num和square。
class ABC{
private static ABC instance;
private int num;
private int square;
private ABC() {}
public static ABC getInstance() {
if (instance == null) {
instance = new ABC();
}
return instance;
}
public int getSquar() {
return square;
}
public void setSquar(int square) {
this.square = square;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
XYZ類(單例)正在調用getter,而ABC類中的setter也是單例。
class XYZ{
private static XYZ instance;
private int result;
private XYZ(){}
public static XYZ getInstance(){
if (instance == null) {
instance = new XYZ();
}
return instance;
}
public void calculateSquare(){
ABC.getInstance().setNum(5);
int n = ABC.getInstance().getNum();
result = calculator(n);
ABC.getInstance().setSquare(result);
}
private int calculator(int n){
return n*n;
}
}
在這里,我正在調用類XYZ的calculateSquare方法。
XYZ.getInstance().calculateSquare();
試圖回答
Mockito:如何驗證由另一個單例的方法調用觸發的單例中的方法調用?
關於
XYZ.getInstance().calculateSquare();
假設您只想使用Mockito和JUnit。
答 :您的“虛擬代碼”是無法測試的代碼的完美示例。
您不能直接測試private
方法,因為您不能調用它們。 如果您認為需要測試private
方法,則不應將其private
。
私有方法隱藏了您不應該針對其編寫任何測試的內部實現。 針對公共API測試編寫測試以了解預期的行為,而不是針對該行為的實現方式編寫代碼(該行為可能由於任何原因而隨時更改,從而很容易破壞您的測試)。
如果要測試代碼,則必須對其進行設計/編碼以使其可測試 。 JUnit / Mockito無法為您使不可測試的代碼可測試。
提示:
用一個簡單的構造函數代替Singleton方法,該構造函數采用實例完成其工作所需的任何依賴的協作者 。 結果變成
public Xyz(final Abc yourCollaborator) {
this.collaborator = yourCollaborator;
}
使用您的Mockito可以創建你的模擬或間諜實例Abc.class
。 您需要一個經過模擬的Abc實例,以將其傳遞到Xyz構造函數中,以進行驗證。 像這樣:
@Test
public void calculateSquareShouldSetNumTo5() throws Exception {
Abc mockedAbc = Mockito.mock(Abc.class);
Xyz xyz = new Xyz(mockedAbc);
// method under test
xyz.calculateSquare();
Mockito.verify(mockedAbc).setNum(5); // expect setNum(5) to be called once
}
要真正對實現進行斷言 ,您需要一個Abc類的真實實例。 因為它是您可以觀察“ calculateSquare()
方法調用的效果”的“部分”。 (請注意,您不能為此使用Mockito模擬的Abc實例!)您的測試可能如下所示:
@Test
public void calculateSquareShouldAlwaysResult25() throws Exception {
Abc abc = new Abc();
Xyz xyz = new Xyz(abc);
// method under test
xyz.calculateSquare();
assertThat(abc.getSquare(), is(25));
}
實際上,最后的測試也可以照原樣為您的“虛擬代碼”編寫:
@Test
public void calculateSquareShouldAlwaysResult25() throws Exception {
// method under test
XYZ.getInstance().calculateSquare();
assertThat(ABC.getInstance().getSquare(), is(25));
}
那么,為什么Singletons仍然對測試不利? 出於測試目的,不能輕易用“占位符”實例替換單例。 這樣的占位符可以是Abc的特殊測試實現,也可以是TestAbc extends Abc
或Mockito模擬的Abc實例。
最后, 如果您將首先編寫測試 (!),則您永遠不會以這種方式編寫“虛擬代碼”。
免責聲明:上面的代碼旨在讓您了解如何進行測試以及“虛擬代碼”需要進行哪些更改才能使其可測試。 這並不意味着有意義的測試,也不意味着這些示例按原樣進行編譯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.