Reputation: 790
I'm working with legacy code and would like to increase the test coverage for it.
I have a class like:
public class MyStrategy implements SomeStrategy {
TimeAndDateUtils timeAndDateUtils = new TimeAndDateUtils();
@Override
public boolean shouldBeExtracted(Argument argument) {
Date currentDate = timeAndDateUtils.getCurrentDate();
return currentDate.isBefore(argument.getDate());
}
}
I would like to test the shouldBeExtracted-Method an mock the call to timeAndDateUtils.getCurrentDate()
so that it returns some fixed value.
So what I'm trying to do is:
Date currentDate = %some fixed date%
TimeAndDateUtils timeAndDateUtils = Mockito.mock(TimeAndDateUtils.class);
Mockito.when(timeAndDateUtils.getCurrentDate()).thenReturn(currentDate);
Assert.assertTrue(myStrategy.shouldBeExtracted(argument))
How can I force the MyStrategy-Class to use the mocked object instead of creating it's own?
Upvotes: 0
Views: 995
Reputation: 44965
Assuming that you cannot rewrite the existing code to make it more testable, this is the typical use case for the annotation @InjectMocks
allowing to inject mock or spy fields into tested object automatically.
@RunWith(MockitoJUnitRunner.class)
public class MyStrategyTest {
@Mock
private TimeAndDateUtils timeAndDateUtils;
@InjectMocks
private MyStrategy myStrategy;
@Test
public void testShouldBeExtracted() {
...
Mockito.when(timeAndDateUtils.getCurrentDate()).thenReturn(currentDate);
Assert.assertTrue(myStrategy.shouldBeExtracted(argument));
}
}
Upvotes: 1
Reputation: 4475
Mockito has a nice class for overriding private objects inside a class. It is called WhiteBox. It works like this
MyStrategy myStrategy = new MyStrategy();
TimeAndDateUtils timeAndDateUtils = Mockito.mock(TimeAndDateUtils.class);
Whitebox.setInternalState(myStartegy, "timeAndDateUtils", timeAndDateUtilsMock);
That will change your TimeAndDateUtils for your mock
Upvotes: 0
Reputation: 247088
timeAndDateUtils
is being created in the class itself which make it difficult to access for test. inject the dependency via constructor so that a mock can be created
public class MyStrategy implements SomeStrategy {
TimeAndDateUtils timeAndDateUtils;
public MyStrategy(TimeAndDateUtils timeAndDateUtils) {
this.timeAndDateUtils = timeAndDateUtils;
}
@Override
public boolean shouldBeExtracted(Argument argument) {
Date currentDate = timeAndDateUtils.getCurrentDate();
return currentDate.isBefore(argument.getDate());
}
}
Test
//Arrange
Date currentDate = %some fixed date%
TimeAndDateUtils timeAndDateUtils = Mockito.mock(TimeAndDateUtils.class);
Mockito.when(timeAndDateUtils.getCurrentDate()).thenReturn(currentDate);
MyStrategy myStrategy = new MyStrategy(timeAndDateUtils);
//Act
bool result = myStrategy.shouldBeExtracted(argument);
//Assert
Assert.assertTrue(result);
Upvotes: 0
Reputation: 1006
You can use reflection to put mock into MyStrategy object. It would look like this:
MyStrategy myStrategy = new MyStrategy(); // I don't know if you are using DI
MyStrategy.class.getDeclaredField("timeAndDateUtils").set(myStrategy, timeAndDateUtilsMock);
Upvotes: 1