views:

35

answers:

1

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.