Reputation: 65
**UPDATE : I have misunderstood the way spys function completely, I should be calling the spy version of a method in order for it to be verified NOT the real object method Ex : r.getPrice(); then verify(r).getPrice(); I still haven't figured the right way to get what i want but i thought i have to ask if i should delete this question ?
I'm spying an array element like this
@Test
public void testMakeCoffee_1() {
Recipe r = spy(stubRecipies[0]);
assertEquals(25,coffeeMaker.makeCoffee(0, 75)); // first index
verify(r).getPrice();
});
this is the implementation of the makeCoffee method
public synchronized int makeCoffee(int recipeToPurchase, int amtPaid) {
int change = 0;
if (getRecipes()[recipeToPurchase] == null) {
change = amtPaid;
} else if (getRecipes()[recipeToPurchase].getPrice() <= amtPaid) {
if (inventory.useIngredients(getRecipes()[recipeToPurchase])) {
change = amtPaid - getRecipes()[recipeToPurchase].getPrice();
} else {
change = amtPaid;
}
} else {
change = amtPaid;
}
return change;
}
getRecipes() implementation inside CoffeeMaker class
public synchronized Recipe[] getRecipes() {
return recipeBook.getRecipes();
}
RecipeBook is a mocked class, stubRecipies is an array that contains my custom recipes to test and getRecipes() of the RecipeBook class is stubbed like this
recipeBookStub = mock(RecipeBook.class);
stubRecipies = new Recipe [] {recipe1, recipe2, recipe3};
when(recipeBookStub.getRecipes()).thenReturn(stubRecipies);
getRecipes() should return the list of recipes, hence replacing it with my array of recipes stubRecipies.
however when i call verify method of mockito on the getPrice() method of the spy object stubRecipies[0] i get a 'wanted but not invoked error' how is it possible that the method is not invoked, knowing that the usage above returns the correct value.
** edit : i tried manually calling recipe1.getPrice() and still i got 'wanted but not invoked error' , but when i called r.getPrice() the test passed which is weird because i thought a spy object is supposed to capture the interactions with the real object.
Upvotes: 1
Views: 856
Reputation: 1240
So from looking at your question and the comments, there are a few things I would recommend to take this forward.
So without seeing the entire code, I can not 100% sure if this is returning the expected Recipe[]
public synchronized Recipe[] getRecipes() {
return recipeBook.getRecipes();
}
You should be injecting your mocked recipeBookStub into your CoffeeMaker.
Typically when writing code in a TDD style we start with the most basic case in this case I would try out the method until oyu can get your method passing:
public int makeCoffee(int recipeToPurchase, int amtPaid) {
getRecipes()[recipeToPurchase]getPrice();
return 25;
}
Another good practice thing is to use as little logic in your test as possible.
rather the:
Recipe r = spy(stubRecipies[0]);
try:
Recipe r = spy(recipe1);
More significantly, the spied object is not being used in CoffeeMaker:
Recipe r = spy(stubRecipies[0]);
r is the mock, and is not the same object as in your array, you can quickly prove this with:
Assert.assertEquals(stubRecipies[0], r);
Assert.assertTrue(stubRecipies[0]== r);
the assertTrue will fail, meaning that stubRecipies[0] is not the same object as the spy (r)
if you set the first index in the array to equal your spied object you might find things work better
Upvotes: 1