我是否以正确的方式使用嘲笑?

时间:2012-01-16 20:25:11

标签: java unit-testing mocking

我有一些传统的东西,想通过测试来掩盖它。 有以下方法,我不知道如何使用模拟测试。

public String listTransactions(Request request, Response response) {
    String transactionFamily = request.get("transactionFamily");
    List transactions = service.fetchTransactions(transactionFamily);
    responseBuilder.addElement("collection", transactions);
    responseBuilder.addElement("token", tokenGenerator.next());
    String  formattedResponse = responseBuilder.build();
    response.send(formattedResponse);
    return null;
}

我的第一个方法是:

public void testResponseIsBuilt() {
    request = stub(Request.class);
    request.method("get").with("transactionFamily").willReturn("dummyFamily");
    response = mock(Response.class);
    response.mehod("send").called(once());
    service = stub(TransactionService.class);
    service.method("fetchTransactions").willReturn(testTransactions);
    responseBuilder = mock(ResponseBuilder.class);
    responseBuilder.method("addElement").called(once()).with("collection", testTransactions);
    responseBuilder.method("addElement").called(once()).with("token", sampleToken);
    responseBuilder.method("build").called(once());     
    responder.setService(service);
    responder.setResponseBuilder(responseBuilder);

    responder.listTransactions(request, response);
}

我知道单个测试用例应该只涵盖SUT的单个方面。因此,考虑到这一点,我可以想象以下一系列测试:

  • testTransactionsFetchedForFamily
  • testTransactionsAddedToResponse
  • testTokenSetInResponse
  • testFormattedResponseBuilt
  • testResponseSent

E.g。执行“testResponseBuilt”我需要像这样设置(如上所述)

  • 存根请求
  • 存根服务
  • 模拟responseBuilder,3期望(2 addElement和1 build)

那不是太多了吗?这种设置不是太复杂吗?我在这里“过度”吗?

我可以考虑将所有的responseBuilder内容放到单独的协作者中,但是对我来说有点疯狂,因为我刚刚提取了ResponseBuilder本身。

我怀疑在这里编写单元测试时我错过了一些重要的观点。

2 个答案:

答案 0 :(得分:2)

这些测试对你来说太过分了。看来你的方法的责任是正确设置和发送响应(从代码判断 - 命名可能会更好,例如,事务 列出现在是什么?)。这就是应该在这里测试的内容。

修改

再看一下,似乎大部分工作都由responseBuilder完成 - 剩下的代码只是设置它。所以你真正可以在这里测试的是它是否提供了预期的数据(这是一次或两次测试),最后是否发送了响应(第二次/第三次测试)。请注意,检查.build是否被调用是不必要的,因为它的缺失会导致响应发送测试失败。

这意味着您需要模仿并验证对responseBuilder.add方法)和response.send)的期望。测试响应格式属于responseBuilder测试,就像测试是否正确获取事务属于service测试一样。

(您也可以验证service是否使用正确的参数进行调用,因为它是硬编码的,但只有在您想要非常谨慎时才会这样做

总的来说,我会完成测试#1和#4,并专注于剩下的测试。

为了验证这些期望,你必须找出剩余的依赖关系。没有真正的方法。您需要在决定编写多少代码以便测试单行代码(以及是否值得)之间找到最佳位置。

答案 1 :(得分:1)

测试套件应包含设置方法,其中应提及请求,服务。这将确保您为所有测试用例重用变量。模块化程度越高,您获得的细粒度响应就越精细。希望这会对你有所帮助。