[英]Unit testing with mockito for constructors
我有一節課。
Class First {
private Second second;
public First(int num, String str) {
second = new Second(str);
this.num = num;
}
... // some other methods
}
我想為 First 類的公共方法編寫單元測試。 我想避免執行類 Second 的構造函數。
我這樣做了:
Second second = Mockito.mock(Second.class);
Mockito.when(new Second(any(String.class))).thenReturn(null);
First first = new First(null, null);
它仍在調用類 Second 的構造函數。 我怎樣才能避免它?
您可以使用PowerMockito
Second second = Mockito.mock(Second.class);
whenNew(Second.class).withNoArguments().thenReturn(second);
但重新分解是更好的決定。
單元測試的問題再次來自使用new
操作符手動創建對象。 考慮傳遞已經創建的Second
:
class First {
private Second second;
public First(int num, Second second) {
this.second = second;
this.num = num;
}
// some other methods...
}
我知道這可能意味着對您的 API 進行重大重寫,但別無他法。 這個類也沒有任何意義:
Mockito.when(new Second(any(String.class).thenReturn(null)));
首先,Mockito 只能模擬方法,不能模擬構造函數。 其次,即使您可以模擬構造函數,您也是在模擬剛剛創建的對象的構造函數,並且從未真正對該對象執行任何操作。
這是使用 PowerMockito API 模擬此功能的代碼。
Second mockedSecond = PowerMockito.mock(Second.class);
PowerMockito.whenNew(Second.class).withNoArguments().thenReturn(mockedSecond);
您需要使用 Powermockito runner 並需要添加所需的測試類(逗號分隔),這些類需要由 powermock API 模擬。
@RunWith(PowerMockRunner.class)
@PrepareForTest({First.class,Second.class})
class TestClassName{
// your testing code
}
我使用過“模式 2 - “工廠助手模式”
模式 2 - 工廠助手模式
這種模式不起作用的一種情況是 MyClass 是最終的。 大多數 Mockito 框架在 final 類中的表現並不是特別好; 這包括使用 spy()。 另一種情況是 MyClass 在某處使用 getClass(),並且要求結果值是 MyClass。 這是行不通的,因為間諜的類實際上是原始類的 Mockito 生成的子類。
在這兩種情況中的任何一種情況下,您都需要稍微更強大的工廠助手模式,如下所示。
public class MyClass{ static class FactoryHelper{ Foo makeFoo( A a, B b, C c ){ return new Foo( a, b, c ); } } //... private FactoryHelper helper; public MyClass( X x, Y y ){ this( x, y, new FactoryHelper()); } MyClass( X x, Y, y, FactoryHelper helper ){ //... this.helper = helper; } //... Foo foo = helper.makeFoo( a, b, c ); }
所以,你有一個特殊的構造函數,只是為了測試,它有一個額外的參數。 在創建要測試的對象時,它會從您的測試類中使用。 在您的測試類中,您模擬 FactoryHelper 類以及您要創建的對象。
@Mock private MyClass.FactoryHelper mockFactoryHelper; @Mock private Foo mockFoo; private MyClass toTest;
你可以像這樣使用它
toTest = new MyClass( x, y, mockFactoryHelper ); when( mockFactoryHelper.makeFoo( any( A.class ), any( B.class ), any( C.class ))) .thenReturn( mockFoo );
來源: http : //web.archive.org/web/20160322155004/http : //code.google.com/p/mockito/wiki/MockingObjectCreation
Mockito 現在可以模擬構造函數(自 3.5.0 版起) https://javadoc.io/static/org.mockito/mockito-core/3.5.13/org/mockito/Mockito.html#mocked_construction
try (MockedConstruction mocked = mockConstruction(Foo.class)) {
Foo foo = new Foo();
when(foo.method()).thenReturn("bar");
assertEquals("bar", foo.method());
verify(foo).method();
}
我相信,不可能使用 mockito 來模擬構造函數。 相反,我建議以下方法
Class First {
private Second second;
public First(int num, String str) {
if(second== null)
{
//when junit runs, you get the mocked object(not null), hence don't
//initialize
second = new Second(str);
}
this.num = num;
}
... // some other methods
}
而且,為了測試:
class TestFirst{
@InjectMock
First first;//inject mock the real testable class
@Mock
Second second
testMethod(){
//now you can play around with any method of the Second class using its
//mocked object(second),like:
when(second.getSomething(String.class)).thenReturn(null);
}
}
將此行包含在測試類的頂部
@PrepareForTest({ First.class })
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.