Sharing knowledge

by Oleg Atamanenko

Initializing Mockito @Mocks with JUnit @Rule

In this post I will show how one can implement custom JUnit @Rule.

As an example let’s take Mockito and implement custom rule which will initialize Mocks in test class.

By default, Mockito provides the following methods of mock initialization:

  1. Using Mockito.mock

    Initialize mocks with Mockito.mock:

    public void FooTest {
            
        private Foo foo;
    
        @Before
        public void setUp() {
            FooDependency dep = Mockito.mock(FooDependency.class);
            foo = new Foo(dep);
        }
    }

    This is the simplest case.

  2. Using MockitoAnnotations. Initialize mocks with MockitoAnnotations:

    public void FooTest {
            
        private Foo foo;
    
        @Mock
        private FooDependency dep;
    
        @Before
        public void setUp() {
            MockitoAnnotations.initMocks(this);
            foo = new Foo(dep);
        }
    }

    This method is useful when you have a lot of mocks to inject.

  3. Using MockitoJUnitRunner

    Initialize mocks with MockitoJUnitRunner:

    @RunWith(MockitoJUnitRunner.class)
    public void FooTest {
            
        private Foo foo;
    
        @Mock
        private FooDependency dep;
    
        @Before
        public void setUp() {
            foo = new Foo(dep);
        }
    }

I want to show you another option, by using custom JUnit @Rule.

First, we need to implement TestRule interface which allows to implement custom behaviour during test execution:

MockitoInitializerRule:

public class MockitoInitializerRule implements TestRule {
    private Object test;

    public MockitoInitializerRule(Object test) {
        this.test = test;
    }

    @Override
    public Statement apply(Statement base, Description description) {
        return new MockitInitilizationStatement(base, test);
    }
}

We need to pass current test class instance to the rule, so it will be possible inject mocks into class instance. Actual implementation of our rule will go to new class - subclass of Statement:

MockitInitilizationStatement:

public class MockitInitilizationStatement extends Statement {
    private final Statement base;
    private Object test;

    MockitInitilizationStatement(Statement base, Object test) {
        this.base = base;
        this.test = test;
    }

    @Override
    public void evaluate() throws Throwable {
        MockitoAnnotations.initMocks(test);
        base.evaluate();
    }
}

What we do is basically initialize mocks in the test class and then proceed with the test method execution.

Now, let’s take a look at the usage of newly created Rule:

Example usage of MockitoInitializerRule:

public void FooTest {
    
    private Foo foo;

    @Mock
    private FooDependency dep;

    @Rule
    public TestRule mockitoInitializerRule = new MockitoInitializerRule(this);

    @Before
    public void setUp() {
        foo = new Foo(dep);
    }
}

Comparing to variant with MockitoJUnitRunner this one provides ability to use custom Runner, i.e. we can continue to use SpringJUnit4ClassRunner

If you have any questions, feel free to ping me on Twitter.

Filed under: articlejavamockitojunitdevelopment

Last update:

Atom.io invites Using AssertJ

comments powered by Disqus