使用模拟对象时测试粒度

时间:2011-12-15 12:35:59

标签: java unit-testing tdd mocking

我有Struts 1动作,想要单独测试它。 这个动作的作用如下:

  • 使用来自请求的参数
  • 加载数据
  • 构建此数据的基于xml的表示
  • 将此回复直接发送给客户

我使用jMock进行测试但在这里有一个疑问。 我的第一个测试是

public void shouldActionInvocationPrintValidResponse() {
    ProcessingAction action = new ProcessingAction();

    DBService service = mock(DBService.class);
    List records = new ArrayList();
    when(service.loadData()).thenReturn(records);

    ResponseBuilder builder = mock(ResponseBuilder.class);
    when(builder.buildResponse(records)).thenReturn("fake response");

    action.execute(null, null, null, null);

    assertEquals("fake response", writer.getContentWritten());
}

我的产品代码对此进行了评估:

public String execute(...) {
    List recordsList = service.loadData();
    String response = responseBuilder.buildResponse(recordsList);
    response.getWriter().print(response);
}

我怀疑这里的测试是不是太大了。我在这里检查整个成功的流程。是不是应该有单独的测试来检查他们自己的测试中的每个依赖调用?

我想知道因为这个测试的名字我遇到了麻烦。我一开始的想法就像是

shouldFetchDataThenFormatThemAndSendResponse

由于这是所有的测试,名称显示它可能做得太多(看看“和”,例如在测试名称中)

我是否应该立即编写完整的测试,或者只是逐步添加依赖项调用?

编辑: 提供测试和操作的详细代码。

3 个答案:

答案 0 :(得分:1)

我认为你走在正确的轨道上。 shouldFetchDataThenFormatThemAndSendResponse 这就说明了一切。在您的测试命名中,您正在讨论实现细节。这就是你应该编写第一个测试的方法。

ProcessingAction action = new ProcessingAction();

Response response = action.execute();

assertEquals(true, response.IsValid);

尝试: shouldGetResponseWhenActionExecuted

现在,您可以查看在执行操作时如何获得响应。

我敢打赌,如果你没有TDD,那就是甜甜圈。

记住:对实施的意图!停止露出你的硬皮内衣。

答案 1 :(得分:0)

如果没有看到代码就很难回答你的问题但是我会给它一个刺。为了使测试成为 Unit 测试,它不应该运行除被测试类中的代码之外的代码。如果你已经模拟了动作调用的每个其他类以及你正在验证的内容只是在被测试的类中完成,那么测试不会太大。我编写了具有大量验证语句的单元测试,因为由于方法的单次调用,所有事情都发生在被测试的类中。

我的单元测试规则是: 1.仅在被测试的类中练习代码 2.每种测试方法只输入一次测试方法

答案 2 :(得分:0)

我同意John B. 此外,如果您使用模拟测试运行器并正确编写它,您可能不需要断言。