What is the main purpose of the @InjectMocks annotation in JUnit tests using Mockito?
Think about how dependencies are provided to the class under test.
@InjectMocks tells Mockito to create an instance of the class and inject all mocks annotated with @Mock or @Spy into it. This helps test the class with its dependencies mocked.
Consider the following JUnit test code snippet using Mockito:
public class ServiceTest {
@Mock
Repository repo;
@InjectMocks
Service service;
@BeforeEach
void setup() {
MockitoAnnotations.openMocks(this);
}
@Test
void testGetData() {
when(repo.getData()).thenReturn("mocked data");
String result = service.getData();
System.out.println(result);
}
}
class Service {
private Repository repo;
public Service(Repository repo) { this.repo = repo; }
public String getData() { return repo.getData(); }
}
interface Repository {
String getData();
}What will be printed when testGetData() runs?
Check how @InjectMocks injects the mock repo into service.
The @InjectMocks annotation creates the service instance and injects the mocked repo. The stubbed method repo.getData() returns "mocked data", so the printed output is "mocked data".
Given the following test setup:
@Mock
Database db;
@InjectMocks
UserService userService;
@BeforeEach
void init() {
MockitoAnnotations.openMocks(this);
}
@Test
void testUserCount() {
when(db.countUsers()).thenReturn(5);
int count = userService.getUserCount();
// Which assertion correctly verifies the behavior?
}Remember what value the mock db.countUsers() returns.
The mock db returns 5 when countUsers() is called. Since userService uses this mock, getUserCount() returns 5. So the correct assertion is assertEquals(5, count);.
In this test code, @InjectMocks does not inject the mocked dependencies, causing a NullPointerException:
@Mock
Dependency dep;
@InjectMocks
MainClass main;
@Test
void testMethod() {
MockitoAnnotations.openMocks(this);
main.call();
}What is the most likely cause of this problem?
Check how Mockito injects mocks into the class under test.
Mockito injects mocks via constructor, setter, or field injection. If MainClass lacks a constructor or setter for dep, Mockito cannot inject the mock, causing NullPointerException.
Consider a class with multiple constructors:
public class Processor {
private final ServiceA a;
private final ServiceB b;
public Processor(ServiceA a) { this.a = a; this.b = null; }
public Processor(ServiceA a, ServiceB b) { this.a = a; this.b = b; }
public String process() {
return (b == null) ? a.action() : b.action();
}
}In a JUnit test with Mockito, @InjectMocks is used on Processor and @Mock on ServiceA and ServiceB. Which constructor will Mockito use to inject mocks?
Mockito prefers constructors with more parameters if mocks are available.
Mockito tries to use the constructor with the most parameters it can satisfy with mocks. Here, both ServiceA and ServiceB mocks exist, so the two-parameter constructor is used.