27

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.

3

4 Answers 4

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

Sign up to request clarification or add additional context in comments.

2 Comments

This + BDDMockito style then(mock).should(times(1)).serviceA();
If you are checking for only one invocation times(1) shouldn't be necessary.
1

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); 

Comments

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.

3 Comments

@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.
what about verifyNoMoreInteractions() ?
@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.
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?

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.