簡體   English   中英

使用 mockito 對構造函數進行單元測試

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM