oreid
oreid

Reputation: 1507

Is it preferred to have a `verify` call for each `when` call in Mockito?

When writing test cases the usual pattern is setup > execute > verify. This results in unit tests that look like this:

@Test
void testSomething() {
    // Setup
    when(someMock.someMethod()).thenReturn("someValue");
    
    // Execute (the doSomething implementation would invoke someMock.someMethod)
    testee.doSomething();
        
    // Verify
    verify(someMock, times(1)).someMethod();
}

My question is, is it necessary to include the verify call considering the when call will raise a UnnecessaryStubbingException exception?

This question only applies in cases where times is 1 since the absence of UnnecessaryStubbingException only implies that someMethod has been called once and with the correct arguments and there may be cases where you want to verify that someMethod has been called never. Without the verify the test would look like this and achieve the same checks:

@Test
void testSomething() {
    // Setup
    when(someMock.someMethod()).thenReturn("someValue");
    
    // Execute (the doSomething implementation would invoke someMock.someMethod)
    testee.doSomething();
}

Edit: A friend pointed out that verifyNoMoreInteractions relies on you having verify calls so I guess this is important to consider.

Edit 2: I've changed "necessary" to "preferred" in the title since I'm more interested in the pros/cons of each approach versus what is technically required.

Thanks in advance!

Upvotes: 0

Views: 1034

Answers (3)

udalmik
udalmik

Reputation: 7988

It is not necessary, as you mentioned - technically test validates this behavior. So the choice should go from preferences and expertise of your team. I personally think having explicit verification step makes your test more readable and maintainable. Few reasons:

  • You can have more when invocations, not relevant to verification logic, this will "hide" the test intention, e.g.
@Test
void testSomething() {
    // Setup
    when(someMock.someMethod()).thenReturn("someValue");
    when(someMock2.someMethod2()).thenReturn("someValue2");
    when(someMock3.someMethod3()).thenReturn("someValue3");
    
    // Execute (the doSomething implementation 
    // would invoke someMock.someMethod)
    testee.doSomething();

    // code reviewer - "hm? what do we really test here?"
}
  • From API perspective throwing of exception in UnnecessaryStubbingException in when is not obvious - this can bring a confusion for occasional code reader who missed that fact. Having verify makes the intention of test clear for almost any developer, even coming from other tech stack
  • Some developers can come from earlier Mockito versions where throwing of UnnecessaryStubbingException was not the case
  • UnnecessaryStubbingException is only raised when Mockito is in strict mode. If this setting is changed to lenient down the line you'd no longer be able to rely on this exception being raised.
  • You can create scenarios where not including verify calls means subsequent verifyNoMoreInteractions calls will fail.

Upvotes: 2

Shailesh Suryawanshi
Shailesh Suryawanshi

Reputation: 1270

No, It is not necessary to add Verify for each when call in Mockito. Every testcase should be deterministic in nature.

To answer your question the preferred way is to use in this particular case is to verifyNoMoreInteractions or verify(somemock, never()).someMethod()

It is not necessary that you always need verify. You can use assertions as well. But, A testcase must have either of them.

For Eg. If you are sure that some method is going to throw an Exception.


@Test(expected = HeyIAmException.class)
void testSomething() {
     classUnderTest.someMethodWhichThrowsException();
}

or In Junit 5.

@Test
void testSomething() {
     when(someMock.someMethod()).thenReturn("someValue");
     HeyIAmException exception = assertThrows(HeyIAmException.class, () ->
                    classUnderTest.someMethodWhichThrowsException()
     );
    
     assertEquals(exception.getCode(),rightCode);
}

In your approach addition to Udalmik's answer I have following more lines to add.

  • We will never know which stub method have caused exception, as any of the someMethod could throw the exception.
  • The intention of the test is not very clear.

Upvotes: 0

HKakrani
HKakrani

Reputation: 11

If you're already aware that your piece of code will throw an exception, its better to have a test case covering it like below

@Test(expected = UnnecessaryStubbingException.class)

A test case(the one you have shown skipping verify) without any assertion or verify statement has no meaning in it. It's a good approach to have verify check for cases when methods have void return type.

Upvotes: 0

Related Questions