Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我使用mock的方法正确吗?_Java_Unit Testing_Mocking - Fatal编程技术网

Java 我使用mock的方法正确吗?

Java 我使用mock的方法正确吗?,java,unit-testing,mocking,Java,Unit Testing,Mocking,我有一些遗留的东西,想通过测试来覆盖它。 我不知道如何使用mock测试以下方法 public String listTransactions(Request request, Response response) { String transactionFamily = request.get("transactionFamily"); List transactions = service.fetchTransactions(transactionFamily); re

我有一些遗留的东西,想通过测试来覆盖它。 我不知道如何使用mock测试以下方法

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的一个方面。考虑到这一点,我可以想象以下一组测试:

  • TestTransactionFetchedForFamily
  • testTransactionsAddedToResponse
  • testTokenSetInResponse
  • testFormattedResponseBuilt
  • 测试响应
例如,要执行“testResponseBuilt”,我需要这样做(如上所述)

  • 存根请求
  • 存根服务
  • 模拟响应构建器,具有3个期望值(2个附加元素和1个构建)
是不是太多了?这样的设置不是太复杂了吗?我在这里“过度模仿”了吗

我可以考虑将所有responseBuilder的东西放在单独的协作器中,但这对我来说有点疯狂,因为我刚刚提取了responseBuilder本身


我怀疑我忽略了在这里编写单元测试的一些要点。

这些测试有些过火了。似乎您的方法的责任是正确设置和发送响应(从代码命名判断可能更好,比如,它现在列出了哪些事务?)。这就是这里应该测试的

编辑:

再看一眼,大部分工作似乎都是由
responseBuilder
完成的,剩下的代码只是对其进行了设置。所以,您真正可以在这里测试的是它是否提供了预期的数据(即一个或两个测试),以及最终是否发送了响应(第二个/第三个测试)。请注意,检查是否调用了
.build
,这并不是必需的,因为它的缺失将导致响应发送测试失败

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

(您也可以验证
service
是用正确的参数调用的,因为它是硬编码的,但这只是在您想非常小心的情况下)

总的来说,我会剔除测试1和测试4,并将重点放在剩下的测试上


为了验证这些期望,您必须去掉剩余的依赖项。这是不可能的。您需要在决定您愿意编写多少代码来测试单行代码(以及是否值得)之间找到最佳点。

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

但为了设定一些模拟预期,我需要在测试中揭示一些内部内容,对吗?为了获得正确的响应格式,我需要准备好responseBuilder,以便为其提供事务和令牌,所以我需要再次展示内部结构。还是我完全迷路了?@grafthez:检查我的编辑-你说得对,你要测试的是responseBuilder是否提供了正确的数据以及是否发送了响应。其他测试属于不同的类。你肯定是对的。我在这里已经讲得很清楚了——在实际实现中,它将转到setUp()。我的问题有点不同:我的实现执行“abcd”,要测试“b”,需要设置“a”。为了测试“c”期望值,我需要设置“AB”,等等……JUnit是为了测试一个流,所以据我所知,您需要为完整的测试用例测试d,并给出c、b和a的断言。您的测试套件应该只包含一个测试流的测试。