23

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 class structure is something like

public class Service {
    public void serviceA(){...}
    public SomeObject serviceB(){...}
    // can grow in the future
}

And Client should be something like

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

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.

Thanks in advance for your answers.

EDIT #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.

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. 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!

Hope this helps to clarify my point and the problem. Best regards.

Community
  • 1
  • 1
Alvaro Pedraza
  • 1,176
  • 6
  • 20
  • 44
  • Possible duplicate of https://stackoverflow.com/questions/12013138/mockito-verify-no-more-interactions-with-any-mock#12013508 – Gonzalo Matheu Jul 13 '17 at 20:30
  • 1
    @GonzaloMatheu: That's a good duplicate since this problem is analogous, but the issue is slightly deeper than just that. – Makoto Jul 13 '17 at 20:30
  • Possible duplicate of [Mockito verify no more interactions with any mock](https://stackoverflow.com/questions/12013138/mockito-verify-no-more-interactions-with-any-mock) – Tom Jul 13 '17 at 20:35

4 Answers4

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

From Mockito's javadoc on 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.

JeanValjean
  • 17,172
  • 23
  • 113
  • 157
Matias Elorriaga
  • 8,880
  • 5
  • 40
  • 58
0

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. 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.

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • @KilleKat: It's the only verifiable way given how the code's written *right now*. If they refactored their code and split up the responsibilities, then no, there would be a better way. – Makoto Jul 13 '17 at 20:35
  • what about verifyNoMoreInteractions() ? – Matias Elorriaga Jul 13 '17 at 20:37
  • @MatiasElorriaga: If the intent is to verify that a method on a mock is *never* called, then `never()` would be appropriate. It's about intent; `verifyNoMoreInteractions` implies that interactions with the mock as a whole happened but don't cleanly convey that a specific method or field on that mock wasn't interacted with. `never()` cleanly tells me as a maintainer and future tester that no, this method was actually never invoked, and is not meant to *ever* be invoked from this method. – Makoto Jul 13 '17 at 20:42
0

I think what you are looking for is the Mockito.verify and 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?

Mafick
  • 1,128
  • 1
  • 12
  • 27
0

To add to what @matias-elorriaga wrote, Mockito 4.0.0 added the method only():

verify(serviceMock, only()).serviceA();

is a shorthand for

verify(serviceMock).serviceA();
verifyNoMoreInteractions(serviceMock);
Aisteru Firë
  • 103
  • 1
  • 4