简体   繁体   English

使用 Mockito.when() 模拟和验证 vs mockito.verify

[英]Using Mockito.when() to mock and verify vs mockito.verify

Imagine you have method someMethod , how would you go by to test it?想象一下你有方法someMethod ,你将如何通过 go 来测试它?

Mockito.when(someClass.someMethod(someParam)).thenReturn(someValue);
var bar = foo() // SUT: ends upp calling someMethod somewhere in the stack
assertThat(bar).isEqualTo(someValue);

vs对比

Mockito.when(someClass.someMethod(someParam)).thenReturn(someValue);
var bar = foo() // SUT: ends upp calling someMethod somewhere in the stack
verify(someClass, times(1)).someMethod(someParam)
assertThat(bar).isEqualTo(someValue);

It is true that the Mockito.when is "kind of" verifying that someClass.someMethod is being called with the correct arguments. Personally I like the idea of having clear assertions/verifications so that the tests can serve as a form of documentation.的确, Mockito.when是“某种程度上”验证正在使用正确的 arguments 调用 someClass.someMethod。我个人喜欢拥有明确断言/验证的想法,以便测试可以作为一种文档形式。 I don't like giving my mocks double-responsibilities, I want to keep my mocks just simply as "mocks".我不喜欢让我的模拟承担双重责任,我想让我的模拟简单地保持为“模拟”。 So back to my question.回到我的问题。

What is the preferred way, using Mockito.when combined with Mockito.verify or only Mockito.when ?什么是首选方式,使用Mockito.when结合Mockito.verify或仅Mockito.when

When defines the behaviour of the Mock - declaratively defining the way the mock will respond when methods are invoked with different parameters. When 定义 Mock 的行为 - 以声明方式定义当使用不同参数调用方法时 mock 将响应的方式。 Verify is used to check whether the Mock has been interacted with in various ways. Verify 用于检查 Mock 是否已通过各种方式进行交互。

Here are some URLS to the official Mockito documentation, which I hope will help.这里有一些Mockito官方文档的网址,希望对你有所帮助。

It's probably worth performing a search for some other examples.可能值得搜索一些其他示例。

I think this question has been answered in https://stackoverflow.com/a/35301264/473064 .我认为这个问题已经在https://stackoverflow.com/a/35301264/473064中得到了解答。

The summary is:总结是:

In short, it is considered good Mockito style to explicitly verify only the interactions that can't be implied from well-crafted stubs and postcondition assertions.简而言之,仅显式验证不能从精心设计的存根和后置条件断言中隐含的交互被认为是良好的 Mockito 风格。 They may be good calls for otherwise-unmeasurable side effects—logging code, thread executors, ArgumentCaptors, multiple method calls, callback functions—but generally should not be applied to stubbed interactions.它们可能是对其他不可测量的副作用的良好调用——记录代码、线程执行器、ArgumentCaptors、多方法调用、回调函数——但通常不应应用于存根交互。

One point that I would add is that sometimes if we want to do a verifyZeroInterations to ensure that no unexpected calls occurred, we would have to first exhaust the known calls by verify ing them.我要补充的一点是,有时如果我们想要执行verifyZeroInterations以确保不会发生意外调用,我们必须首先通过verify耗尽已知调用。

What I usually do is to perform the simplest verify(mock, times(n)).someMethod(anyClass()) as generally as possible without repeating the more specific argument matching that I have already specified in the stubbing, which reduces the duplication as much as possible.我通常做的是尽可能一般地执行最简单的verify(mock, times(n)).someMethod(anyClass())而不重复我已经在存根中指定的更具体的参数匹配,这减少了重复尽可能多。

Example:例子:

when(someObject.someMethod(eq("abc"))).thenReturn(someValue);
when(someObject.someMethod(eq("def"))).thenReturn(otherValue);
when(someObject.someMethod(endsWith("suffix"))).thenReturn(anotherValue);

var bar = foo();

assertEquals(expectedBar, bar);

verify(someObject, times(3)).someMethod(anyString());
verifyZeroInteractions(someObject);

Regarding your concern in the comment:关于您在评论中的担忧:

The problem I see is, if a new developer reads the test, they won't know the subbed method is part of the verification process.我看到的问题是,如果新开发人员阅读测试,他们不会知道 subbed 方法是验证过程的一部分。

The stubbed method is not part of the verification process.存根方法不是验证过程的一部分。 It's part of the test case setup, ie, the Given step.它是测试用例设置的一部分,即Given步骤。

I think your example might be a little bit misleading.我认为你的例子可能有点误导。 The final output from foo() is usually a transformation of the response from someMethod , ie, someValue in the example.来自foo()的最终 output 通常是来自someMethod的响应的转换,即示例中的someValue So if the stubbed method is not called and returned with the correct value, the test would have failed anyway.因此,如果存根方法没有被调用并返回正确的值,测试无论如何都会失败。 The said developer would then have to look at the mocking and understand how the test case works.然后,所述开发人员必须查看 mocking 并了解测试用例的工作原理。

In the updated example below, there is no need to verify that someMethod is called because if it didn't get called, the assertion would fail.在下面更新的示例中,无需验证someMethod是否被调用,因为如果它没有被调用,断言就会失败。

Mockito.when(someClass.someMethod(someParam)).thenReturn(someValue);
var bar = foo() // SUT: ends upp calling someMethod somewhere in the stack
var expectedValue = // a value depending on `someValue`
assertThat(bar).isEqualTo(expectedValue);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM