assylias assylias - 4 months ago 6
Java Question

Check that a method is not invoked

I want to check that a method is not run and tried to do it with an Expectation setting

times = 0;
, however I don't get the expected behaviour.

For example, the following test passes, although the
Session#stop
method is called, and the expectation has a
times = 0;
condition:

public static class Session {
public void stop() {}
}

public static class Whatever {
Session s = new Session();
public synchronized void method() {
s.stop();
}
}

@Test
public void testWhatever () throws Exception {
new Expectations(Session.class) {
@Mocked Session s;
{ s.stop(); times = 0; } //Session#stop must not be called
};
final Whatever w = new Whatever();
w.method(); // this method calls Session#stop => the test should fail...
// ... but it passes
}


Note: If I replace the code with
{ s.stop(); times = 1; }
, the test passes too: I must be missing something obvious here...

Answer

The reason of the unexpected mocking behavior is that you inadvertently used partial mocking on an strictly mocked type. In this case, recording an expectation with times = <n> means that the first n matching invocations will be mocked, and after that any additional invocations will execute the original "unmocked" method. With regular mocking instead, you would get the expected behavior (ie, an UnexpectedInvocation getting thrown after n invocations).

The proper way to write the test is:

public static class Session { public void stop() {} }
public static class Whatever {
    Session s = new Session();
    public synchronized void method() { s.stop(); }
}

@Test
public void testWhatever ()
{
    new Expectations() {
        @Mocked Session s;
        { s.stop(); times = 0; }
    };

    final Whatever w = new Whatever();
    w.method();
}

Alternatively, it can also be written with a verification block instead, which is usually better for situations like these:

@Test
public void testWhatever (@Mocked final Session s)
{
    final Whatever w = new Whatever();
    w.method();

    new Verifications() {{ s.stop(); times = 0; }};
}