Search code examples
javajmockit

Is an Expectations block without a result the same thing as a Verifications block?


I understand that in general, Expectations are used to mock values with differnt return values. For instance:

new Expectations() {{
    bar.getGreeting();
    result = "Hello, world!";
    times = 2;
}};

I have noticed that result is optional though. At that point, this block just confirms that the method was called twice and throws a MissingInvocation error if it is not. So for instance:

@Test
public void testRunFoo(@Mocked final Bar bar) {
    Foo foo = new Foo(bar);
    new Expectations() {{
        bar.runBar();
        times = 2;
    }};

    foo.runFooWithBarTwice(); //Successful
    //foo.runFooWithoutBar(); //Will throw a MissingInvocationException
}

I have noticed that this code appears to be the same thing as using Verifications instead:

@Test
public void testRunFoo(@Mocked final Bar bar) {
    Foo foo = new Foo(bar);

    foo.runFooWithBarTwice(); //Successful
    //foo.runFooWithoutBar(); //Will throw a MissingInvocationException

    new Verifications() {{
        bar.runBar();
        times = 2;
    }};
}

Is an Expectations block without a result the same thing as a Verifications block? Can you use either according to your personal preference? Or is there some subtle difference between the two that I'm missing?


Solution

  • You are correct that they both will work similarly. If you mock interactions in an Expectations block, they will be verified similarly to placing them in an Verifications block.

    If you look at the design philosophy of JMockit in the introduction page at http://jmockit.org/gettingStarted.html, it recommends writing tests with the following pattern

    @Test
    public void aTestMethod(<any number of mock parameters>)
    {
       // Record phase: expectations on mocks are recorded; empty if nothing to record.
    
       // Replay phase: invocations on mocks are "replayed"; code under test is exercised.
    
       // Verify phase: expectations on mocks are verified; empty if nothing to verify.
    }
    

    The purpose of the Record phase is not to verify your code under test, but to ensure the code you are testing has the dependencies and interactions it needs to run the test. Thus the purpose of an Expectations block is to record any interactions in which your mock objects need to do something specific to interact with your code under test in the Replay phase. This typically means returning specific values or ensuring the correct mocked object is used for an interaction.

    I sometimes put the three comments from the JMockit docs above in my unit tests to help in documentation of the test.

    Finally, the Verifications block is where you are typically going to do your verification of your mock object interactions. Note that you can also use standard Junit assertions before, after, or within a Verifications block.