简体   繁体   English

Mockito验证仅调用了预期的方法

[英]Mockito verify that ONLY a expected method was called

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类和某种充当外观的Client的项目中工作(不知道这在Design Patterns的世界中是否是正确的术语,但我会尽力使自己更清楚)。 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方法。

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" . 节中,我想是这样verifyOnly(serviceMock).serviceA():“验证serviceMock.serviceA()被调用一次,并从没有其他方法Service类被称为”。 Is there something like that in Mockito or in some other mocking library? Mockito或其他模拟库中是否有类似的东西? 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. 我不想对每种方法都使用verify(serviceMock, never()).serviceXXX() ,因为正如我所说, Service类将来可能会增长,我将不得不在每个测试中添加验证(不满意)任务),所以我需要一些更一般的东西。

Thanks in advance for your answers. 预先感谢您的回答。

EDIT #1 编辑#1

The difference between this post and the possible duplicate is 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, verifyNoMoreInteractions can be a good option even when it's discouraged for every test, no extra boiler plate code needed. 同样,即使不建议每次测试都使用verifyNoMoreInteractions ,也不需要额外的模板代码。

To sumarize, the possible duplicate didn'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 article quoted in the mockito documentation for verifyNoMoreInteractions . 还有另一个问题:我正在编写针对另一个团队编写的代码的测试,而不是自己遵循TDD流程编写的,因此我的测试应该具有额外的防御性 ,正如在嘲讽文档中对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! 也许verifyNoMoreInteractions已经足够好了,但是我希望看到由相同的API创建者团队进行的每项测试都不会令人沮丧!

Hope this helps to clarify my point and the problem. 希望这有助于阐明我的观点和问题。 Best regards. 最好的祝福。

verify(serviceMock, times(1)).serviceA();
verifyNoMoreInteractions(serviceMock);

From Mockito's javadoc on verifyNoMoreInteractions : 从Mockito的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(),即使在每种测试方法中也是如此。 verifyNoMoreInteractions() is not recommended to use in every test method. 不建议在每种测试方法中都使用verifyNoMoreInteractions()。 verifyNoMoreInteractions() is a handy assertion from the interaction testing toolkit. verifyNoMoreInteractions()是来自交互测试工具包的便捷断言。 Use it only when it's relevant. 仅在相关时使用。 Abusing it leads to overspecified, less maintainable tests. 滥用它会导致规范过度,难以维护的测试。

The only way you can reliably verify that your service is only ever called once and only once from the method you specify and not from any other method, is to test every single method and assert that your serviceA method is never invoked. 只有这样,您可以可靠地验证您的服务只会被调用一次,从您指定,而不是从任何其他方法的方法只有一次,是检验每一个方法 ,并断言,你serviceA方法不会被调用。 But you're testing every other method anyway , so this shouldn't be that much of a lift... 但是无论如何 ,您都在测试其他所有方法,所以这应该不算什么...

// 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. 从那里开始,您的测试用例和代码周围的保证变得越来越小,越来越固定。

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: 这是另一个有相同问题的线程:

Mockito: How to verify a method was called only once with exact parameters ignoring calls to other methods? Mockito:如何验证一个方法仅被调用一次且其确切参数忽略对其他方法的调用?

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

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