Book Image

MOCKITO COOKBOOK

By : Grzejszczak
Book Image

MOCKITO COOKBOOK

By: Grzejszczak

Overview of this book

This is a focused guide with lots of practical recipes with presentations of business issues and presentation of the whole test of the system. This book shows the use of Mockito's popular unit testing frameworks such as JUnit, PowerMock, TestNG, and so on. If you are a software developer with no testing experience (especially with Mockito) and you want to start using Mockito in the most efficient way then this book is for you. This book assumes that you have a good knowledge level and understanding of Java-based unit testing frameworks.
Table of Contents (12 chapters)
11
Index

Adding Mockito hints to exception messages (JUnit) (Experimental)

When a JUnit test fails, an exception is thrown and a message is presented. Sometimes, it is enough to find a reason for this mistake and to find the solution. Mockito, however, goes a step further and tries to help the developer by giving him additional hints regarding the state of the stubbed methods.

Note

Remember that this feature is experimental and the API, name, or anything related to it may change in time. What is more, the whole feature may get deleted in time!

Getting ready

For this recipe, let's assume that our system is the MeanTaxFactorCalculator class that calculates tax through TaxService, which has two methods—performAdditionalCalculation() and getCurrentTaxFactorFor(...). For the sake of this example, let's assume that only the latter is used to calculate the mean value:

public class MeanTaxFactorCalculator {

    private final TaxService taxService;

    public MeanTaxFactorCalculator(TaxService taxService) {
        this.taxService = taxService;
    }

    public double calculateMeanTaxFactorFor(Person person) {
        double currentTaxFactor = taxService.getCurrentTaxFactorFor(person);
        double anotherTaxFactor = taxService.getCurrentTaxFactorFor(person);
        return (currentTaxFactor + anotherTaxFactor) / 2;
    }

}

We wanted to check whether our system under test is calculating the proper result, so we wrote the following test but made a mistake and stubbed a wrong method (I'm using the BDDMockito.given(...) and AssertJ's BDDAssertions.then(...) static methods—refer Chapter 7, Verifying Behavior with Object Matchers, for how to work with AssertJ or how to do the same with Hamcrest's assertThat(...) method):

@RunWith(MockitoJUnitRunner.class)
public class MeanTaxFactorCalculatorTest {

    static final double UNUSED_VALUE = 10;

    @Test
    public void should_calculate_mean_tax_factor() {
        // given
        TaxService taxService = given(Mockito.mock(TaxService.class).performAdditionalCalculation()).willReturn(UNUSED_VALUE).getMock();
        MeanTaxFactorCalculator systemUnderTest =new MeanTaxFactorCalculator(taxService);

        // when
        double meanTaxFactor = systemUnderTest.calculateMeanTaxFactorFor(new Person());

        // then
        then(meanTaxFactor).isEqualTo(UNUSED_VALUE);
    }

}

The test fails and what we can see is the standard JUnit comparison failure being thrown (presenting only the most important part of the stack trace) as follows:

org.junit.ComparisonFailure:
Expected :10.0
Actual   :0.0

Now let's take a look at how to use Mockito's experimental features to get more Mockito related information appended to the error message.

How to do it...

If you want to have more information presented in your error message, you have to perform the following steps:

  1. Annotate your JUnit test with @RunWith(VerboseMockitoJUnitRunner.class).
  2. Define your mocks and perform stubbing inside the test method (unfortunately, you can't use annotations or initialize fields outside test methods).

What happens next is that additional exception messages can be seen in the exception that is thrown as follows:

org.mockito.internal.exceptions.ExceptionIncludingMockitoWarnings:contains both: actual test failure *and* Mockito warnings.
This stubbing was never used   -> at ...MeanTaxFactorCalculatorTest.should_calculate_mean_tax_factor(MeanTaxFactorCalculatorTest.java:30)

 *** The actual failure is because of: ***

Expected :10.0
Actual   :0.0

How it works...

When the test is run, VerboseMockitoJUnitRunner appends a listener. When the test is started, this listener finds all the stubs through WarningsCollector, including the unused stubs for given mocks.

As the Mockito developers state it in the code, they are indeed using a very hacky way to append a message to the thrown exception after the test fails. The JUnitFailureHacker class is instantiated and, by means of the Whitebox class, the internal state of a private field of the JUnit's Failure object is modified with additional Mockito messages.