繁体   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