簡體   English   中英

具有嵌套依賴項的測試類

[英]Test class with nested dependencies

我正在測試具有嵌套(自動裝配)依賴項的類。 該類實現用於在后端進行更改的businesslogic。 具體來說,測試應斷言某個后端調用返回錯誤時:

  • 不再進行后端調用
  • 響應對象返回錯誤

我不知道后者該怎么辦。 我的課看起來像這樣:

public class Handler {

    @Autowired
    private DaoImpl dao;

    @Autowired
    private SpecificUtil util1;

    @Autowired
    private GeneralUtil util2;

    @Autowired
    private Helper helper;

    public Response doSomethingClever(Request request) {
    // calls to dao
    // logic with help of util and helper classes
    }
}

測試類:

public class HandlerTest {

@Spy
private DaoImpl dao;

@Mock
private SpecificUtil util1;

@Mock
private GeneralUtil util2;

@Mock
private Helper helper;

@InjectMocks
Handler handler;

@Test
public void testDoSomethingClever() {
    // set up dao to fail
    QueryResult error = getErrorResult();
    org.mockito.Mockito.when(dao.queryBackEnd(any(SpecificQuery.class))).thenReturn(error);

    // perform query
    Request request = getTestRequest();
    Response errorResponse = handler.doSomethingClever(request);

    // verify that either:
    // Response has errors - fails 
    // because helper classes are mocks, have not set the error 
    assertNotNull(response.getErrorMessage());

    // the method setErrors of Response was called once - fails 
    //because the setError was called earlier!
    Response spyResponse = Mockito.spy(errorResponse);
    verify(spyResponse, times(1)).setError(anyString);

    //verify no other calls are made except the queryBackEnd call - this part  works
    org.mockito.Mockito.verify(dao).queryBackEnd(any(SpecificQuery.class));
    org.mockito.Mockito.verifyNoMoreInteractions(dao);
}

}

在Handler類中創建Response對象。 如果我檢查返回的響應,則Mockito將不會記錄任何交互,因為交互是在調用Mockito.spy之前發生的。

我嘗試通過使用@Spy而不是@Mock使其成為集成測試。 這個想法是實例化除dao之外的所有嵌套依賴項,並獲得適當的Response以測試錯誤。 但這是行不通的,因為某些@Autowired幫助程序和實用程序類也具有@Autowired依賴關系,並且這些嵌套的依賴關系在測試期間不會實例化。

有沒有辦法用Mockito將@Spy對象注入到其他@Spy對象中? 還是在這種情況下還有其他解決方案? 我可以編寫自己的模擬對象嗎?

單元測試應僅測試特定單元的代碼(此處為Handler類)。 這包括與依賴項進行交互。

從您在問題和評論中所寫的內容來看, handle方法的外觀大致如下:

public class Handler {

    @Autowired
    private DaoImpl dao;

    @Autowired
    private Util util;

    public Response doSomethingClever(Request request) {
        SpecificQuery specificQuery = new SpecificQuery();
        specificQuery.setSomeData(request.getSomeData());

        IntermidiateResponse intermidiateResponse = dao.queryBackEnd(specificQuery);
        Response response = util.processIntermidiateResult(intermidiateResult);

        return response;
    }
}

這里有一些要進行單元測試的交互:

  • 給定一個Request實例,就可以斷言使用SpecificQuery實例調用DaoImpl::queryBackEnd方法,該實例具有將Request對象的someData屬性設置為someData屬性
  • 給定一個嘲笑IntermidiateResponse從返回DaoImpl::queryBackEnd方法斷言這一結果是到過Util::processIntermidiateResult方法
  • 給定從Util::processIntermidiateResult方法返回的模擬Response ,則斷言這正是從handle方法返回的內容

這樣,您對Handler::handle方法的覆蓋率為100%。 如果響應處理管道中還有其他一些調用,則可以對它們進行相應的測試。

希望這能回答您的問題。 祝好運

有兩種選擇,一種是單獨測試Handler,模擬其他所有東西。 請參閱jannis答案 另一個選擇是控制/模擬Handler的輸入和輸出,並將Handler 及其所有實用程序類視為黑匣子。

我選擇了最后一個選項,因為這意味着我可以重構實用程序類和Handler類本身,並且只要我不更改Handler的功能,測試就可以成功。 確實意味着我已經脫離了單元測試的范圍,而我實際上正在做更多的集成測試。

為此,我模擬了Dao類,以便可以讓它在所需的點返回錯誤,並可以斷言在錯誤之后不再進行任何調用。 這是我模擬的唯一類,因此我需要將其注入到Handler中。 Springs ReflectionTestUtils可以做到這一點(我昨天不知道這件事)

然后,測試代碼變得更短:

public class HandlerTest {

  @Autowired
  private Handler handler;

  @Test
  public void testDoSomethingClever() {

  // set up dao to fail
  Dao  mockDao = org.mockito.Mockito.mock(DaoImpl.class);
  QueryResult error = getErrorResult();
  org.mockito.Mockito.when(dao.queryBackEnd(any  (SpecificQuery.class))).thenReturn(error);

  // inject the dao
  ReflectionTestUtils.setField(handler, "dao", mockDao);

  // perform query
  Request request = getTestRequest();
  Response errorResponse = handler.doSomethingClever(request);

  // verify that Response has errors 
  assertNotNull(response.getErrorMessage());

  //verify no other calls are made except the queryBackEnd call
  org.mockito.Mockito.verify(dao).queryBackEnd(any(SpecificQuery.class));
  org.mockito.Mockito.verifyNoMoreInteractions(dao);
 }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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