java Mockito 验证仅调用了预期的方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45090331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mockito verify that ONLY a expected method was called
提问by Alvaro Pedraza
I'm working in a Project with a Service
class and some sort of a Client
that acts as a facade (don't know if it's the right term in the Design Patterns's world, but I'll try to make myself clear). Service
's methods can be very expensive as they may be communicating with one or more databases, long checkings and so on, so every Client
method should call one and only one Service
method.
我正在一个项目中工作,其中包含一个Service
类和某种Client
充当外观的类(不知道这是否是设计模式世界中的正确术语,但我会尽量让自己清楚)。Service
的方法可能非常昂贵,因为它们可能与一个或多个数据库通信、长时间检查等,因此每个Client
方法都应该调用一个且仅一个Service
方法。
Service
class structure is something like
Service
类结构类似于
public class Service {
public void serviceA(){...}
public SomeObject serviceB(){...}
// can grow in the future
}
And Client
should be something like
而且Client
应该是这样的
public class Client {
private Service myService; // Injected somehow
public void callServiceA() {
// some preparation
myService.serviceA();
// something else
}
public boolean callServiceB(){...}
}
And in the test class for Client
I want to have something like
在测试课中,Client
我想要一些类似的东西
public class ClientTest{
private Client client; // Injected or instantiated in @Before method
private Service serviceMock = mock(Service.class);
@Test
public void callServiceA_onlyCallsServiceA() {
client.callServiceA();
????
}
}
In the ????
section I want something like verifyOnly(serviceMock).serviceA()
saying "verify that serviceMock.serviceA()
was called only once and no other method from the Service
class was called". Is there something like that in Mockito or in some other mocking library? I don't want to use verify(serviceMock, never()).serviceXXX()
for every method because, as I said, Service
class may grow in the future and I will have to be adding verification to every test (not a happy task for me) so I need something more general.
在该????
部分中,我verifyOnly(serviceMock).serviceA()
想说“验证serviceMock.serviceA()
只调用一次并且没有Service
调用类中的其他方法”。Mockito 或其他一些模拟库中是否有类似的东西?我不想verify(serviceMock, never()).serviceXXX()
对每一种方法都使用,因为正如我所说,Service
类将来可能会增长,我将不得不为每个测试添加验证(对我来说不是一项快乐的任务)所以我需要一些更通用的东西。
Thanks in advance for your answers.
预先感谢您的回答。
EDIT #1
编辑#1
The difference between this post and the possible duplicateis that the answer adds boiler plate code which is not desired in my case because it's a very big project and I must add as few code as posible.
这篇文章与可能的重复文章之间的区别在于答案添加了样板代码,这在我的情况下是不想要的,因为这是一个非常大的项目,我必须尽可能少地添加代码。
Also, verifyNoMoreInteractionscan be a good option even when it's discouraged for every test, no extra boiler plate code needed.
此外,即使每次测试都不鼓励使用verifyNoMoreInteractions也是一个不错的选择,不需要额外的样板代码。
To sumarize, the possible duplicatedidn't solved my problem.
总而言之,可能的重复并没有解决我的问题。
There's another issue: I'm writing test for code made by another team, not following a TDD proccess myself, so my test should be extra defensive, as stated in this articlequoted in the mockito documentation for verifyNoMoreInteractions. The methods I'm testing are often very longs so I need to check that the method under test calls ONLY the necesary services and no other (because they're expensive, as I said). Maybe verifyNoMoreInteractions
is good enough for now but I'd like to see something not being discouraged for every test by the very same API creator team!
还有另一个问题:我正在为另一个团队编写的代码编写测试,而不是自己遵循 TDD 过程,所以我的测试应该是额外的防御性,正如在verifyNoMoreInteractions的 mockito 文档中引用的这篇文章中所述。我正在测试的方法通常很长,所以我需要检查被测方法是否只调用必要的服务而不调用其他服务(因为它们很昂贵,正如我所说)。也许现在已经足够好了,但我希望看到同一个 API 创建者团队在每次测试中都不会气馁!verifyNoMoreInteractions
Hope this helps to clarify my point and the problem. Best regards.
希望这有助于澄清我的观点和问题。最好的祝福。
回答by Matias Elorriaga
verify(serviceMock, times(1)).serviceA();
verifyNoMoreInteractions(serviceMock);
From Mockito's javadoc on verifyNoMoreInteractions:
从 Mockito's javadoc 关于verifyNoMoreInteractions:
You can use this method after you verified your mocks - to make sure that nothing else was invoked on your mocks.
您可以在验证模拟后使用此方法 - 以确保在模拟上没有调用任何其他内容。
Also:
还:
A word of warning: Some users who did a lot of classic, expect-run-verify mocking tend to use verifyNoMoreInteractions() very often, even in every test method. verifyNoMoreInteractions() is not recommended to use in every test method. verifyNoMoreInteractions() is a handy assertion from the interaction testing toolkit. Use it only when it's relevant. Abusing it leads to overspecified, less maintainable tests.
警告:一些进行了很多经典的、expect-run-verify 模拟的用户倾向于非常频繁地使用 verifyNoMoreInteractions(),即使在每个测试方法中也是如此。不建议在每个测试方法中使用 verifyNoMoreInteractions()。verifyNoMoreInteractions() 是来自交互测试工具包的一个方便的断言。仅在相关时使用它。滥用它会导致过度指定、不易维护的测试。
回答by Makoto
The onlyway you can reliably verify that your service is only ever called once and only once from the method you specify and not from any othermethod, is to test every single methodand assert that your serviceA
method is never invoked. But you're testing every other method anyway, so this shouldn't be that much of a lift...
该只可以可靠地验证一次且仅一次从方法您可以从任何指定,而不是你的服务只会被调用方式等方法,是测试每一个方法,并断言,你的serviceA
方法不会被调用。但是无论如何你都在测试其他所有方法,所以这不应该是一个很大的提升......
// In other test cases...
verify(serviceMock, never()).serviceA();
While this is undesirable from a code writing standpoint, it opens the door to separating out your service into smaller, more responsible chunks so that you guarantee that only one specific service is called. From there, your test cases and guarantees around your code become smaller and more ironclad.
虽然从代码编写的角度来看这是不可取的,但它为将您的服务分成更小、更负责任的块打开了大门,以便您保证只调用一个特定的服务。从那里开始,您的代码周围的测试用例和保证变得更小、更可靠。
回答by Mafick
I think what you are looking for is the Mockito.verify and Mockito.times
我想你正在寻找的是 Mockito.verify 和 Mockito.times
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
verify(mockObject, atLeast(2)).someMethod("was called at least twice");
verify(mockObject, times(3)).someMethod("was called exactly three times");
Here another thread with the same question:
这是另一个具有相同问题的线程: