I’m still learning mockito and right now I’m learning how to inject mocks.
I have an object under test with a particular method that depends on other objects. Those objects, in turn, depend on other objects. I want to mock certain things and have those mocks be used everywhere during execution–throughout the control flow of the method.
For example assume there are classes like:
public class GroceryStore {
public double inventoryValue = 0.0;
private shelf = new Shelf(5);
public void takeInventory() {
for(Item item : shelf) {
inventoryValue += item.price();
}
}
}
public class Shelf extends ArrayList<Item> {
private ProductManager manager = new ProductManager();
public Shelf(int aisleNumber){
super(manager.getShelfContents(aisleNumber);
}
}
public class ProductManager {
private Apple apple;
public void setApple(Apple newApple) {
apple = newApple;
}
public Collection<Item> getShelfContents(int aisleNumber) {
return Arrays.asList(apple, apple, apple, apple, apple);
}
}
I need to write test code with portions along the lines of:
....
@Mock
private Apple apple;
...
when(apple.price()).thenReturn(10.0);
...
...
@InjectMocks
private GroceryStore store = new GroceryStore();
...
@Test
public void testTakeInventory() {
store.takeInventory();
assertEquals(50.0, store.inventoryValue);
}
Whenever apple.price() is called, I want my mock apple to be the one used. Is this possible?
EDIT:
Important note…
the class that contains the object I want to mock does have a setter for that object. However, I don’t really have a handle to that class at the level I’m testing. So, following the example, although ProductManager has a setter for Apple, I don’t have a way of getting the ProductManager from the GroceryStore object.
The problem is you create objects you depend on by calling
newinstead of injecting it. InjectProductManagerintoShelf(e.g. in constructor), and injectShelfintoGroceryStore. Then in test use mocks. If you want to use@InjectMocks, you have to inject by setter methods.By constructor it could look like this:
Then you can test it mocking all the objects you depend on: