我有一些传统的东西,想通过测试来掩盖它。 有以下方法,我不知道如何使用模拟测试。
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的单个方面。因此,考虑到这一点,我可以想象以下一系列测试:
E.g。执行“testResponseBuilt”我需要像这样设置(如上所述)
那不是太多了吗?这种设置不是太复杂吗?我在这里“过度”吗?
我可以考虑将所有的responseBuilder内容放到单独的协作者中,但是对我来说有点疯狂,因为我刚刚提取了ResponseBuilder本身。
我怀疑在这里编写单元测试时我错过了一些重要的观点。
答案 0 :(得分:2)
这些测试对你来说太过分了。看来你的方法的责任是正确设置和发送响应(从代码判断 - 命名可能会更好,例如,事务 列出现在是什么?)。这就是应该在这里测试的内容。
修改强>
再看一下,似乎大部分工作都由responseBuilder
完成 - 剩下的代码只是设置它。所以你真正可以在这里测试的是它是否提供了预期的数据(这是一次或两次测试),最后是否发送了响应(第二次/第三次测试)。请注意,检查.build
是否被调用是不必要的,因为它的缺失会导致响应发送测试失败。
这意味着您需要模仿并验证对responseBuilder
(.add
方法)和response
(.send
)的期望。测试响应格式属于responseBuilder
测试,就像测试是否正确获取事务属于service
测试一样。
(您也可以验证service
是否使用正确的参数进行调用,因为它是硬编码的,但只有在您想要非常谨慎时才会这样做
总的来说,我会完成测试#1和#4,并专注于剩下的测试。
为了验证这些期望,你必须找出剩余的依赖关系。没有真正的方法。您需要在决定编写多少代码以便测试单行代码(以及是否值得)之间找到最佳位置。
答案 1 :(得分:1)
测试套件应包含设置方法,其中应提及请求,服务。这将确保您为所有测试用例重用变量。模块化程度越高,您获得的细粒度响应就越精细。希望这会对你有所帮助。