83

Using Mockito in Java how to verify a method was called only once with exact parameters ignoring calls to other methods?

Sample code:

public class MockitoTest {

    interface Foo {
        void add(String str);
        void clear();
    }


    @Test
    public void testAddWasCalledOnceWith1IgnoringAllOtherInvocations() throws Exception {
        // given
        Foo foo = Mockito.mock(Foo.class);

        // when
        foo.add("1"); // call to verify
        foo.add("2"); // !!! don't allow any other calls to add()
        foo.clear();  // calls to other methods should be ignored

        // then
        Mockito.verify(foo, Mockito.times(1)).add("1");
        // TODO: don't allow all other invocations with add() 
        //       but ignore all other calls (i.e. the call to clear())
    }

}

What should be done in the TODO: don't allow all other invocations with add() section?

Already unsuccessfully tried:

  1. verifyNoMoreInteractions(foo);

Nope. It does not allow calls to other methods like clear().

  1. verify(foo, times(0)).add(any());

Nope. It does not take into account that we allow one call to add("1").

Igor Mukhin
  • 15,014
  • 18
  • 52
  • 61
  • How about using [verifyNoMoreInteractions](http://site.mockito.org/mockito/docs/1.10.19/org/mockito/Mockito.html#verifyNoMoreInteractions(java.lang.Object...))? – SpaceTrucker Sep 12 '16 at 14:21
  • then it will say "the call to clear() is not expected" but we want to ignore calls to all methods except add() – Igor Mukhin Sep 12 '16 at 14:24
  • ignore means you want to fail the test case in this case? – hunter Sep 12 '16 at 14:25
  • "ignore" means "The test results does not depend on what happend there" – Igor Mukhin Sep 12 '16 at 14:27
  • One way I can think of right now is to change the mock to throw an exception if anything other then "1" is passed as parameter. Edit: below answer is better. – mdewit Sep 12 '16 at 14:27
  • Nice idea with the exception, but sometimes it is a Spy so you can't change the behaviour. – Igor Mukhin Sep 12 '16 at 14:29

3 Answers3

132
Mockito.verify(foo, Mockito.times(1)).add("1");
Mockito.verify(foo, Mockito.times(1)).add(Mockito.anyString());

The first verify checks the expected parametrized call and the second verify checks that there was only one call to add at all.

Igor Mukhin
  • 15,014
  • 18
  • 52
  • 61
hunter
  • 3,963
  • 1
  • 16
  • 19
  • if add method calls 2 or more times, then second line will fail, if add method calls only once with a different argument first line will fail. so this make sure that add method is called once with given argument , but not called with other arguments. – hunter Sep 12 '16 at 14:36
  • 1
    add this last line to ur code, test will fail. then comment the line foo.add("1"); . then test will fail. then uncomment it and comment foo.add("2"); then test will pass. that's what u want right – hunter Sep 12 '16 at 14:38
  • You are absolutely right! You will get the checkmark! Thank you! – Igor Mukhin Sep 12 '16 at 14:43
  • Is there no way to set kind of a @Rule for mockito to fail by default if when isn't set for this method? – Johnny_D Jul 03 '19 at 00:10
  • It was the second line I didn't understand was checking the total number of calls until I tried it. So the following 3rd line would fail if there was a 3rd call to the method (with any arg) that my test wasn't aware of: verify(mock, times(1)).method(eq(expectedParam)); verify(mock, times(1)).method(eq(expectedParam2)); verify(mock, times(2)).method(any()); – Skystrider Jun 29 '23 at 21:41
  • So ensure method isn't called: verify(mock, times(0)).method(any()); – Skystrider Jun 29 '23 at 21:45
40

The previous answer can be simplified even further.

Mockito.verify(foo).add("1");
Mockito.verify(foo).add(Mockito.anyString());

The single parameter verify method is just an alias to the times(1)implementation.

Travis Miller
  • 449
  • 4
  • 4
  • 9
    This simplification does provide value if you are primarily concerned with minimizing character count. However the accepted Answer has value too, in that it is more explicit as to the times: It makes it clear 1x times, whereas the code in this answer would only express that via looking at the JavaDoc for #verify. The accepted Answer would be more immediately clear to a coder who is not familiar with #validate defaults, and might not otherwise have a reason to look at its Javadoc. – cellepo Sep 08 '17 at 22:24
  • any() should be used when never() is used. verify(x, never()).method(anyString()) – kristjan reinhold Nov 12 '18 at 14:00
0
verify(mock.methodName()).called(1// or any number that u should check);
Reza Taghizadeh
  • 347
  • 5
  • 11