Annotation Magic with Mockito: InjectMocks

If you are not testing your code, you are just creating garbage. To avoid this we require a way to generate mocks for our classes to test our code.

Mockito is a simple, yet elegant way to inject mocks into your code without making a mess of it.

Read on to know how you can do this.

 

What is Mockito?

Mockito is a mocking framework designed for unit testing in Java. It allows you to write simple tests with a clean API. Tests written with this framework are easy to read and produce clean verification errors.

The key benefits of using Mockito are,

  • It has a friendly and massive StackOverflow community and thorough documentation, voted as the best mocking framework for Java.
  • Easy to use and understand as a first time mocker.
  • The @InjectMocks annotation makes it easier and cleaner to inject mocks into your code.

@InjectMocks

@InjectMocks is the Mockito Annotation. It allows you to mark a field on which an injection is to be performed.

Injection allows you to,

  • Enable shorthand mock and spy injections.
  • Minimize repetitive mock and spy injection.

Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection, in order. If any of the following strategies fail, then Mockito won't report a failure.

From the Mockito Documentation,

    1. Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only. If the object is successfully created with the constructor, then Mockito won't try the other strategies. Mockito has decided not to corrupt an object if it has a parameterized constructor.
      1. Note: If arguments can not be found, then null is passed. If non-mockable types are wanted, then constructor injection won't happen. In these cases, you will have to satisfy dependencies yourself.
    2. Property setter injection; mocks will first be resolved by type (if a single type match injection will happen regardless of the name), then, if there are several properties of the same type, by the match of the property name and the mock name.
      1. Note 1: If you have properties with the same type (or same erasure), it's better to name all @Mock annotated fields with the matching properties, otherwise Mockito might get confused and injection won't happen.
      2. Note 2: If @InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.
    3. Field injection; mocks will first be resolved by type (if a single type match injection will happen regardless of the name), then, if there is several property of the same type, by the match of the field name and the mock name.
      1. Note 1: If you have fields with the same type (or same erasure), it's better to name all @Mock annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.
      2. Note 2: If @InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.

Examples

public class ArticleManagerTest extends SampleBaseTestCase {

@Mock private ArticleCalculator calculator;
@Mock(name = "database") private ArticleDatabase dbMock; // note the mock name attribute
@Spy private UserProvider userProvider = new ConsumerUserProvider();

@InjectMocks private ArticleManager manager;

@Test public void shouldDoSomething() {
manager.initiateArticle();
verify(database).addListener(any(ArticleListener.class));
}
}

public class SampleBaseTestCase {

@Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
}

In the above example the field ArticleManager annotated with @InjectMocks could have a parameterized constructor only, a no-arg constructor only, or both.

All these constructors can be package protected, protected, or private. However, Mockito cannot instantiate inner classes, local classes, abstract classes, and, of course, interfaces. Beware of private nested static classes, too.

The same stands for setters or fields, they can be declared with private visibility. Mockito will see them through reflection. However, fields that are static or final will be ignored.

The constructor injection would look like this,

 public class ArticleManager {
ArticleManager(ArticleCalculator calculator, ArticleDatabase database) {
// parameterized constructor
}
}

Property setter injection would like this,

 public class ArticleManager {
// no-arg constructor
ArticleManager() { }

// setter
void setDatabase(ArticleDatabase database) { }

// setter
void setCalculator(ArticleCalculator calculator) { }
}

Field injection, like this,

 public class ArticleManager {
private ArticleDatabase database;
private ArticleCalculator calculator;
}

Always remember that the @InjectMocks annotation will only inject mocks/spies created using @Mock or @Spy annotations.

Finally…

Basically this annotation is an injection interface as it generates a new Mock from a designated object with specified properties. It then injects it as a “dependency” of sorts, and allows you to use it for further testing.

If you have any questions, contact me at rraya@nearsoft.com.

For more check out the first part of our Mockito series.

Share this post

Table of Contents