ChatGPT解决这个技术问题 Extra ChatGPT

How to verify that a specific method was not called using Mockito?

How to verify that a method is not called on an object's dependency?

For example:

public interface Dependency {
    void someMethod();
}

public class Foo {
    public bar(final Dependency d) {
        ...
    }
}

With the Foo test:

public class FooTest {
    @Test
    public void dependencyIsNotCalled() {
        final Foo foo = new Foo(...);
        final Dependency dependency = mock(Dependency.class);
        foo.bar(dependency);
        **// verify here that someMethod was not called??**
    }
}

M
Michael Xin Sun

Even more meaningful :

import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

// ...

verify(dependency, never()).someMethod();

The documentation of this feature is there §4 "Verifying exact number of invocations / at least x / never", and the never javadoc is here.


Using never is the best and most specific way, but if you need to check an entire mock object, also consider verifyZeroInteractions(mockObject) or verifyNoMoreInteractions(mockObject).
what to do if someMethod is private??
Then you can not mock it in the first place (with Mockito) ;) PowerMock allows to that but it's more complex to set up. Or if you have ownership of the code, you relax the visibility to package.
Since 3.0.1 verifyZeroInteractions has been deprecated. verifyNoInteractions is the suggested a alternative. Mockito version at the time of this comment is 3.3.3
N
Naman

Use the second argument on the Mockito.verify method, as in:

Mockito.verify(dependency, Mockito.times(0)).someMethod()

public static VerificationMode never() { return times(0); }
never() is not significantly more readable than times(0). But the existence of never does increase cognitive load and makes the mockito system harder to understand and remember how to use. So really mockito shouldn't have included never in their API, its not worth the mental cost.
Question: does this form verify that someMethod was called 0 times, or does it only verify that someMethod was never called with zero arguments?
@B T - I would imagine it verifies the someMethod with zero arguments was called zero times- not verified.
Same works for jmockit btw, times=0;
D
David Lavender

As a more general pattern to follow, I tend to use an @After block in the test:

@After
public void after() {
    verifyNoMoreInteractions(<your mock1>, <your mock2>...);
}

Then the test is free to verify only what should be called.

Also, I found that I often forgot to check for "no interactions", only to later discover that things were being called that shouldn't have been.

So I find this pattern useful for catching all unexpected calls that haven't specifically been verified.


The Mockito documentation states that this pattern should not be abused -- "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." See here
"Use it only when it's relevant". I feel that it is always relevant. I don't see that pattern as abuse: like I said, it finds "things were being called that shouldn't have been". To me, that's a vital piece of verification: if something is calling a repository that it shouldn't be using, I want to know about it! Unless there's another way to verify that without using verifyNoMoreInteractions? The other answers here rely on the test writer explicitly remembering to list out these checks: that's too error prone in my book.
I saw this comment, but also felt like the reasoning was not compelling. I would love to read more about why this is not recommended.
@tobinibot Because the idea of unit testing is to verify a Contract. Most contracts don't typically involved how many times some other method is invoked, but rather that passing in known parameters results in a known response. By using no more interactions you're basically verifying the implementation line by line, which makes refactoring and implementation tedious. Which isn't the point of unit testing.
I've run into multiple times where we verify something was not called, then later change the implementation to call something else.. and the old test still passes, because the old method is still not called, but we didn't verify the new method. The pattern suggested here will help ensure your test stays relevant - if you update code without updating a test, you may have hidden issues and assume your test still covers it. I agree with @DavidLavender: "The other answers here rely on the test writer explicitly remembering to list out these checks: that's too error prone in my book."
f
fl0w

First of all: you should always import mockito static, this way the code will be much more readable (and intuitive):

import static org.mockito.Mockito.*;

There are actually many ways to achieve this, however it's (arguably) cleaner to use the

verify(yourMock, times(0)).someMethod();

method all over your tests, when on other Tests you use it to assert a certain amount of executions like this:

verify(yourMock, times(5)).someMethod();

Alternatives are:

verify(yourMock, never()).someMethod();

Alternatively - when you really want to make sure a certain mocked Object is actually NOT called at all - you can use:

verifyZeroInteractions(yourMock)

Please Note: verifyZeroInteractions(Object... mocks) is Deprecated. Since Version 3.0.1. The now recommended method is:

verifyNoInteractions(yourMock)

b
byxor

Both the verifyNoMoreInteractions() and verifyZeroInteractions() method internally have the same implementation as:

public static transient void verifyNoMoreInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

public static transient void verifyZeroInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

so we can use any one of them on mock object or array of mock objects to check that no methods have been called using mock objects.


Transient is for fields
A
Alex Blasco

Just as a suggestion, if you want to be more aligned at syntax level with Behavior-driven development style there is BDDMockito:

You could use:

then(dependency).should(never()).someMethod();

As an equivalent replacement of:

verify(dependency, never()).someMethod();