Mockito: Injection grinding throughout the control flow

I'm still learning mockito, and now I'm teaching how to introduce ridicule.

I have an object under test with a specific method that depends on other objects. These objects, in turn, depend on other objects. I want to mock certain things and use them in all cases at runtime - in the entire method control flow.

For example, suppose classes exist such as:

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 parts in rows:

 .... @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 breadboard apple to be used. Is it possible?

EDIT:
Important Note ...
the class containing the object I want to make fun of has a customization tool for this object. However, I have no help for this class at the level I'm testing. So, following the example, although ProductManager has a suite for Apple, I have no way to get the ProductManager from the GroceryStore object.

+4
source share
1 answer

The problem is that you are creating objects that you depend on by calling new instead of typing it. Add the ProductManager to Shelf (for example, in the constructor) and enter Shelf into the GroceryStore . Then the mockery is used in the test. If you want to use @InjectMocks , you need to introduce setter methods.

By constructor, it may look like this:

 public class GroceryStore { public double inventoryValue = 0.0; private shelf; public GroceryStore(Shelf shelf) { this.shelf = shelf; } public void takeInventory() { for(Item item : shelf) { inventoryValue += item.price(); } } } public class Shelf extends ArrayList<Item> { private ProductManager manager; public Shelf(int aisleNumber, ProductManager manager) { super(manager.getShelfContents(aisleNumber); this.manager = manager; } } 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); } } 

Then you can test it by mocking all the objects you depend on:

 @Mock private Apple apple; ... when(apple.price()).thenReturn(10.0); @InjectMocks private ProductManager manager = new ProductManager(); private Shelf shelf = new Shelf(5, manager); private GroceryStore store = new GroceryStore(shelf); //Then you can test your store. 
+2
source

All Articles