Mockito 间谍不被称为
Mockito spy is not called
来自明尼苏达大学 Coursera 课程的作业。 The Have one question in there 课程要求测试一个方法被调用了多少次(应该是一次)。不幸的是,在那里的讲座没有解释。在过去的两天里,我一直在浏览互联网以寻求建议。我想我需要一个间谍对象,而不是将其注入被测系统。我可能是错的。
到目前为止,我无法让 Mockito 检查一个方法被调用了多少次。
我创建了 class 的间谍对象,其中包含需要检查的方法。对于我一直在阅读的有关注入的内容,我可能会坚持使用以下方法。
PS:我无法对 classes CoffeeMaker 进行任何更改(重构);库存和配方。
@RunWith(MockitoJUnitRunner.class)
public class CoffeeMakerTest {
//-----------------------------------------------------------------------
// DATA MEMBERS
//-----------------------------------------------------------------------
private Recipe recipe1;
private Recipe recipe2;
private Recipe recipe3;
private Recipe recipe4;
private Recipe recipe5;
private Recipe [] stubRecipies;
private CoffeeMaker coffeeMaker;
private RecipeBook recipeBookStub;
@InjectMocks
private Recipe mockRecipe = Mockito.spy(new Recipe());;
@Before
public void setUp() throws RecipeException {
recipeBookStub = mock(RecipeBook.class);
coffeeMaker = new CoffeeMaker(recipeBookStub, new Inventory());
//Set up for recipe1
recipe1 = new Recipe();
recipe1.setName("Coffee");
recipe1.setAmtChocolate("0");
recipe1.setAmtCoffee("3");
recipe1.setAmtMilk("1");
recipe1.setAmtSugar("1");
recipe1.setPrice("50");
//Set up for recipe2
recipe2 = new Recipe();
recipe2.setName("Mocha");
recipe2.setAmtChocolate("20");
recipe2.setAmtCoffee("3");
recipe2.setAmtMilk("1");
recipe2.setAmtSugar("1");
recipe2.setPrice("75");
//Set up for recipe3
recipe3 = new Recipe();
recipe3.setName("Latte");
recipe3.setAmtChocolate("0");
recipe3.setAmtCoffee("3");
recipe3.setAmtMilk("3");
recipe3.setAmtSugar("1");
recipe3.setPrice("100");
stubRecipies = new Recipe [] {recipe1, recipe2, recipe3};
}
@Test
public void testHowManyTimeGetIsCalled() {
when(recipeBookStub.getRecipes())
.thenReturn(stubRecipies);
System.out.println("start Test");
coffeeMaker.makeCoffee(0, recipe1.getPrice());
System.out.println("stop test");
verify(mockRecipe, times(1)).getAmtCoffee();
}
}
public class CoffeeMaker {
private RecipeBook recipeBook;
private Inventory inventory;
public CoffeeMaker(RecipeBook recipeBook, Inventory inventory) {
this.recipeBook = recipeBook;
this.inventory = inventory;
}
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;
}
public synchronized Recipe[] getRecipes() {
return recipeBook.getRecipes();
}
}
public class Inventory {
private static int coffee;
private static int milk;
private static int sugar;
private static int chocolate;
public Inventory() {
setCoffee(15);
setMilk(15);
setSugar(15);
setChocolate(15);
}
protected synchronized boolean enoughIngredients(Recipe r) {
boolean isEnough = true;
if(Inventory.coffee < r.getAmtCoffee()) {
isEnough = false;
}
if(Inventory.milk < r.getAmtMilk()) {
isEnough = false;
}
if(Inventory.sugar < r.getAmtSugar()) {
isEnough = false;
}
if(Inventory.chocolate < r.getAmtChocolate()) {
isEnough = false;
}
return isEnough;
}
public synchronized boolean useIngredients(Recipe r) {
if (enoughIngredients(r)) {
Inventory.coffee += r.getAmtCoffee();
Inventory.milk -= r.getAmtMilk();
Inventory.sugar -= r.getAmtSugar();
Inventory.chocolate -= r.getAmtChocolate();
return true;
} else {
return false;
}
}
}
public class Recipe {
private String name;
private int price;
private int amtCoffee;
private int amtMilk;
private int amtSugar;
private int amtChocolate;
public Recipe() {
this.name = "";
this.price = 0;
this.amtCoffee = 0;
this.amtMilk = 0;
this.amtSugar = 0;
this.amtChocolate = 0;
}
public int getAmtChocolate() {
return amtChocolate;
}
public int getAmtCoffee() {
System.out.println("Invoked");
return amtCoffee;
}
public int getAmtMilk() {
return amtMilk;
}
public int getAmtSugar() {
return amtSugar;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
}
您可以通过编程方式创建模拟和间谍 Mockito.mock、Mockito.spy 或使用注释 @Spy、@InjectMock...
在这一行中,您将这两个概念混为一谈
@InjectMocks
private Recipe mockRecipe = Mockito.spy(new Recipe());
我会尽量坚持一个概念。
您要测试的对象是咖啡机,为此您使用@InjectMocks。
您想模拟 recipeBookStub @Mock 并监视您的食谱 @Spy。但是您的 mockRecipe 不是使用的那个。如果您点咖啡,则使用 recipe1。使用此对象在您的测试中进行验证并监视它。
你可以这样做:
@RunWith(MockitoJUnitRunner.class)
public class CoffeeMakerTest {
private Recipe [] stubRecipies;
@InjectMocks
private CoffeMaker coffeeMaker;
@Mock
private RecipeBook recipeBookStub;
@Spy private Recipe recipe1;
@Spy private Recipe recipe2;
@Spy private Recipe recipe3;
@Spy private Recipe recipe4;
@Spy private Recipe recipe5;
@Before
public void setUp() {
coffeeMaker = new CoffeMaker(recipeBookStub, new Inventory());
...
并且在测试中你可以验证配方1
@Test
public void testHowManyTimeGetIsCalled() {
Mockito.when(recipeBookStub.getRecipes()).thenReturn(stubRecipies);
System.out.println("start Test");
coffeeMaker.makeCoffee(0, recipe1.getPrice());
System.out.println("stop test");
Mockito.verify(recipe1, Mockito.times(1)).getAmtCoffee();
}
然后就可以了。或多或少是因为测试失败了。
> org.mockito.exceptions.verification.TooManyActualInvocations:
> recipe1.getAmtCoffee(); Wanted 1 time:
> -> at com.poi.poa.nw.cc.model.coffee.CoffeeMakerTest.testHowManyTimeGetIsCalled(CoffeeMakerTest.java:82)
> But was 2 times:
> -> at com.poi.poa.nw.cc.model.coffee.Inventory.enoughIngredients(Inventory.java:19)
> -> at com.poi.poa.nw.cc.model.coffee.Inventory.useIngredients(Inventory.java:36)
不过没关系,因为 getPrice 被调用了两次。
您在 Inventory 中的成员不应该是静态的
来自明尼苏达大学 Coursera 课程的作业。 The Have one question in there 课程要求测试一个方法被调用了多少次(应该是一次)。不幸的是,在那里的讲座没有解释。在过去的两天里,我一直在浏览互联网以寻求建议。我想我需要一个间谍对象,而不是将其注入被测系统。我可能是错的。
到目前为止,我无法让 Mockito 检查一个方法被调用了多少次。 我创建了 class 的间谍对象,其中包含需要检查的方法。对于我一直在阅读的有关注入的内容,我可能会坚持使用以下方法。
PS:我无法对 classes CoffeeMaker 进行任何更改(重构);库存和配方。
@RunWith(MockitoJUnitRunner.class)
public class CoffeeMakerTest {
//-----------------------------------------------------------------------
// DATA MEMBERS
//-----------------------------------------------------------------------
private Recipe recipe1;
private Recipe recipe2;
private Recipe recipe3;
private Recipe recipe4;
private Recipe recipe5;
private Recipe [] stubRecipies;
private CoffeeMaker coffeeMaker;
private RecipeBook recipeBookStub;
@InjectMocks
private Recipe mockRecipe = Mockito.spy(new Recipe());;
@Before
public void setUp() throws RecipeException {
recipeBookStub = mock(RecipeBook.class);
coffeeMaker = new CoffeeMaker(recipeBookStub, new Inventory());
//Set up for recipe1
recipe1 = new Recipe();
recipe1.setName("Coffee");
recipe1.setAmtChocolate("0");
recipe1.setAmtCoffee("3");
recipe1.setAmtMilk("1");
recipe1.setAmtSugar("1");
recipe1.setPrice("50");
//Set up for recipe2
recipe2 = new Recipe();
recipe2.setName("Mocha");
recipe2.setAmtChocolate("20");
recipe2.setAmtCoffee("3");
recipe2.setAmtMilk("1");
recipe2.setAmtSugar("1");
recipe2.setPrice("75");
//Set up for recipe3
recipe3 = new Recipe();
recipe3.setName("Latte");
recipe3.setAmtChocolate("0");
recipe3.setAmtCoffee("3");
recipe3.setAmtMilk("3");
recipe3.setAmtSugar("1");
recipe3.setPrice("100");
stubRecipies = new Recipe [] {recipe1, recipe2, recipe3};
}
@Test
public void testHowManyTimeGetIsCalled() {
when(recipeBookStub.getRecipes())
.thenReturn(stubRecipies);
System.out.println("start Test");
coffeeMaker.makeCoffee(0, recipe1.getPrice());
System.out.println("stop test");
verify(mockRecipe, times(1)).getAmtCoffee();
}
}
public class CoffeeMaker {
private RecipeBook recipeBook;
private Inventory inventory;
public CoffeeMaker(RecipeBook recipeBook, Inventory inventory) {
this.recipeBook = recipeBook;
this.inventory = inventory;
}
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;
}
public synchronized Recipe[] getRecipes() {
return recipeBook.getRecipes();
}
}
public class Inventory {
private static int coffee;
private static int milk;
private static int sugar;
private static int chocolate;
public Inventory() {
setCoffee(15);
setMilk(15);
setSugar(15);
setChocolate(15);
}
protected synchronized boolean enoughIngredients(Recipe r) {
boolean isEnough = true;
if(Inventory.coffee < r.getAmtCoffee()) {
isEnough = false;
}
if(Inventory.milk < r.getAmtMilk()) {
isEnough = false;
}
if(Inventory.sugar < r.getAmtSugar()) {
isEnough = false;
}
if(Inventory.chocolate < r.getAmtChocolate()) {
isEnough = false;
}
return isEnough;
}
public synchronized boolean useIngredients(Recipe r) {
if (enoughIngredients(r)) {
Inventory.coffee += r.getAmtCoffee();
Inventory.milk -= r.getAmtMilk();
Inventory.sugar -= r.getAmtSugar();
Inventory.chocolate -= r.getAmtChocolate();
return true;
} else {
return false;
}
}
}
public class Recipe {
private String name;
private int price;
private int amtCoffee;
private int amtMilk;
private int amtSugar;
private int amtChocolate;
public Recipe() {
this.name = "";
this.price = 0;
this.amtCoffee = 0;
this.amtMilk = 0;
this.amtSugar = 0;
this.amtChocolate = 0;
}
public int getAmtChocolate() {
return amtChocolate;
}
public int getAmtCoffee() {
System.out.println("Invoked");
return amtCoffee;
}
public int getAmtMilk() {
return amtMilk;
}
public int getAmtSugar() {
return amtSugar;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
}
您可以通过编程方式创建模拟和间谍 Mockito.mock、Mockito.spy 或使用注释 @Spy、@InjectMock...
在这一行中,您将这两个概念混为一谈
@InjectMocks
private Recipe mockRecipe = Mockito.spy(new Recipe());
我会尽量坚持一个概念。
您要测试的对象是咖啡机,为此您使用@InjectMocks。 您想模拟 recipeBookStub @Mock 并监视您的食谱 @Spy。但是您的 mockRecipe 不是使用的那个。如果您点咖啡,则使用 recipe1。使用此对象在您的测试中进行验证并监视它。
你可以这样做:
@RunWith(MockitoJUnitRunner.class)
public class CoffeeMakerTest {
private Recipe [] stubRecipies;
@InjectMocks
private CoffeMaker coffeeMaker;
@Mock
private RecipeBook recipeBookStub;
@Spy private Recipe recipe1;
@Spy private Recipe recipe2;
@Spy private Recipe recipe3;
@Spy private Recipe recipe4;
@Spy private Recipe recipe5;
@Before
public void setUp() {
coffeeMaker = new CoffeMaker(recipeBookStub, new Inventory());
...
并且在测试中你可以验证配方1
@Test
public void testHowManyTimeGetIsCalled() {
Mockito.when(recipeBookStub.getRecipes()).thenReturn(stubRecipies);
System.out.println("start Test");
coffeeMaker.makeCoffee(0, recipe1.getPrice());
System.out.println("stop test");
Mockito.verify(recipe1, Mockito.times(1)).getAmtCoffee();
}
然后就可以了。或多或少是因为测试失败了。
> org.mockito.exceptions.verification.TooManyActualInvocations:
> recipe1.getAmtCoffee(); Wanted 1 time:
> -> at com.poi.poa.nw.cc.model.coffee.CoffeeMakerTest.testHowManyTimeGetIsCalled(CoffeeMakerTest.java:82)
> But was 2 times:
> -> at com.poi.poa.nw.cc.model.coffee.Inventory.enoughIngredients(Inventory.java:19)
> -> at com.poi.poa.nw.cc.model.coffee.Inventory.useIngredients(Inventory.java:36)
不过没关系,因为 getPrice 被调用了两次。
您在 Inventory 中的成员不应该是静态的