org.mockito
@Documented @Target(value=FIELD) @Retention(value=RUNTIME) public @interface InjectMocks
Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won't report failure; i.e. you will have to provide dependencies yourself.
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.
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.
Note 2: If @InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.
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.
Note 2: If @InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.
Example:
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
can have
a parameterized constructor only or 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 nest 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.
So on the field that needs injection, for example constructor injection will happen here :
public class ArticleManager {
ArticleManager(ArticleCalculator calculator, ArticleDatabase database) {
// parameterized constructor
}
}
Property setter injection will happen here :
public class ArticleManager {
// no-arg constructor
ArticleManager() { }
// setter
void setDatabase(ArticleDatabase database) { }
// setter
void setCalculator(ArticleCalculator calculator) { }
}
Field injection will be used here :
public class ArticleManager {
private ArticleDatabase database;
private ArticleCalculator calculator;
}
And finally, no injection will happen on the type in this case:
public class ArticleManager {
private ArticleDatabase database;
private ArticleCalculator calculator;
ArticleManager(ArticleObserver observer, boolean flag) {
// observer is not declared in the test above.
// flag is not mockable anyway
}
}
Again, note that @InjectMocks will only inject mocks/spies created using the @Spy or @Mock annotation.
MockitoAnnotations.initMocks(this)
method has to be called to initialize annotated objects.
In above example, initMocks()
is called in @Before (JUnit4) method of test's base class.
For JUnit3 initMocks()
can go to setup()
method of a base class.
Instead you can also put initMocks() in your JUnit runner (@RunWith) or use the built-in
MockitoJUnitRunner
.
Mockito is not an dependency injection framework, don't expect this shorthand utility to inject a complex graph of objects be it mocks/spies or real objects.
Mock
,
Spy
,
MockitoAnnotations.initMocks(Object)
,
MockitoJUnitRunner