Mockito - how to verify that a mock was never invoked

JavaJunitMockito

Java Problem Overview


I'm looking for a way to verify with Mockito, that there wasn't any interaction with a given mock during a test. It's easy to achieve that for a given method with verification mode never(), but I haven't found a solution for the complete mock yet.

What I actually want to achieve: verify in tests, that nothing get's printed to the console. The general idea with jUnit goes like that:

private PrintStream systemOut;

@Before
public void setUp() {
    // spy on System.out
    systemOut = spy(System.out);
}

@After
public void tearDown() {
    verify(systemOut, never());  // <-- that doesn't work, just shows the intention
}

A PrintStream has tons of methods and I really don't want to verify each and every one with separate verify - and the same for System.err...

So I hope, if there's an easy solution, that I can, given that I have a good test coverage, force the software engineers (and myself) to remove their (my) debug code like System.out.println("Breakpoint#1"); or e.printStacktrace(); prior to committing changes.

Java Solutions


Solution 1 - Java

Use this :

import static org.mockito.Mockito.verifyZeroInteractions;

// ...

private PrintStream backup = System.out;

@Before
public void setUp() {
    System.setOut(mock(PrintStream.class));
}

@After
public void tearDown() {
    verifyZeroInteractions(System.out);
    System.setOut(backup);
}

Solution 2 - Java

verifyZeroInteractions(systemOut);

As noted in comments, this doesn't work with a spy.

For a roughly equivalent but more complete answer, see the answer by gontard to this question.

Solution 3 - Java

Since the original correct answer, verifyZeroInteractions has been deprecated, use verifyNoInteractions instead:

import org.junit.jupiter.api.Test;

import static org.mockito.Mockito.*;

public class SOExample {

    @Test
    public void test() {
        Object mock = mock(Object.class);
        verifyNoInteractions(mock);
    }
}

Solution 4 - Java

You could try a slightly different tack:

private PrintStream stdout;

@Before public void before() {
    stdout = System.out;
    OutputStream out = new OutputStream() {
        @Override public void write(int arg0) throws IOException {
            throw new RuntimeException("Not allowed");
        }
    };
    System.setOut(new PrintStream(out));
}

@After public void after() {
    System.setOut(stdout);
}

If you preferred, you could switch the anonymous type for a mock and verify as Don Roby suggests.

Solution 5 - Java

One way of solving this problem is to refactor the class that you're testing, to allow for the injection of a PrintStream that can be used for output. This will let you unit test it, without relying on the behaviour of the System class. You could use a package-private constructor for this injection, since you'll only ever use it from the corresponding test class. So it might look something like this.

public class MyClass{
    private PrintWriter systemOut;

    public MyClass(){
        this(System.out);
    }

    MyClass(PrintWriter systemOut){
        this.systemOut = systemOut;

        // ...any other initialisation processing that you need to do
    }
}

and within the class itself, use the systemOut variable instead of System.out wherever you call the latter.

Now, within the test class, make a mock PrintStream, and pass it to the package-private constructor, to get the object that you're going to test. Now you can run any actions you like from your tests, and use verify to check their effects on your mock PrintStream.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndreas DolkView Question on Stackoverflow
Solution 1 - JavagontardView Answer on Stackoverflow
Solution 2 - JavaDon RobyView Answer on Stackoverflow
Solution 3 - JavaRobert BainView Answer on Stackoverflow
Solution 4 - JavaMcDowellView Answer on Stackoverflow
Solution 5 - JavaDawood ibn KareemView Answer on Stackoverflow