1. Objective
We want to test a business class (SomeBusinessImpl) that depends on another component (SomeDataService). Traditionally, we would manually create a mock and inject it into the business class. However, Mockito offers a more elegant way to handle this using the @Mock and @InjectMocks annotations.
2. Problem Statement
Suppose we have the following scenario:
SomeBusinessImplis a class with a dependency onSomeDataService.- In our tests, we want to mock
SomeDataServiceand inject it intoSomeBusinessImpl. - Previously, we manually created both the mock and the instance of
SomeBusinessImpland wired them together.
This is common in unit testing with Mockito. But Mockito provides a cleaner way using annotations.
3. Step-by-Step Guide
3.1 Traditional Approach (Manual Injection)
SomeDataService dataServiceMock = mock(SomeDataService.class); SomeBusinessImpl business = new SomeBusinessImpl(); business.setSomeDataService(dataServiceMock);
This works but is verbose and repetitive.
3.2 Improved Approach using @Mock and @InjectMocks
Mockito allows you to simplify the above setup with annotations:
@RunWith(MockitoJUnitRunner.class)
public class SomeBusinessTest {
@Mock
private SomeDataService dataServiceMock;
@InjectMocks
private SomeBusinessImpl business;
@Test
public void testCalculateSumUsingDataService() {
when(dataServiceMock.retrieveAllData()).thenReturn(new int[] {1, 2, 3});
int result = business.calculateSumUsingDataService();
assertEquals(6, result);
}
}
3.3 What Happens Under the Hood?
@Mocktells Mockito to create a mock instance ofSomeDataService.@InjectMockstells Mockito to create an instance ofSomeBusinessImpland inject any@Mockfields into it.@RunWith(MockitoJUnitRunner.class)ensures that Mockito’s annotation processor is active during the test run.
4. Benefits
- Less boilerplate code.
- Cleaner, more readable tests.
- Encourages better separation of concerns and test structure.
