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:
SomeBusinessImpl
is a class with a dependency onSomeDataService
.- In our tests, we want to mock
SomeDataService
and inject it intoSomeBusinessImpl
. - Previously, we manually created both the mock and the instance of
SomeBusinessImpl
and 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?
@Mock
tells Mockito to create a mock instance ofSomeDataService
.@InjectMocks
tells Mockito to create an instance ofSomeBusinessImpl
and inject any@Mock
fields 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.