想要使用 mockito returns 监视数组元素,但在调用方法时未调用

spying an array element with mockito returns wanted but not invoked when the method is invoked

**更新:我完全误解了 spys 的运行方式,我应该调用一个方法的 spy 版本以便对其进行验证,而不是真正的对象方法 Ex:r.getPrice();然后验证(r).getPrice();我仍然没有想出获得我想要的东西的正确方法,但我想我必须问我是否应该删除这个问题?

我正在监视这样的数组元素

@Test
public void testMakeCoffee_1() {
    Recipe r = spy(stubRecipies[0]);

    assertEquals(25,coffeeMaker.makeCoffee(0, 75)); // first index

            verify(r).getPrice();
});

这是 makeCoffee 方法的实现

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;
}

CoffeeMaker 中的 getRecipes() 实现 class

public synchronized Recipe[] getRecipes() {
    return recipeBook.getRecipes();
}

RecipeBook 是一个模拟的 class,stubRecipies 是一个包含我要测试的自定义食谱的数组,RecipeBook class 的 getRecipes() 是这样存根的

recipeBookStub = mock(RecipeBook.class);
stubRecipies = new Recipe [] {recipe1, recipe2, recipe3};
when(recipeBookStub.getRecipes()).thenReturn(stubRecipies);

getRecipes() 应该 return 食谱列表,因此用我的食谱 stubRecipies 数组替换它。

然而,当我在间谍对象 stubRecipies[0] 的 getPrice() 方法上调用 mockito 的验证方法时,我得到一个 'wanted but not invoked error' 知道用法怎么可能不调用该方法以上 return 是正确的值。

** 编辑:我尝试手动调用 recipe1.getPrice() 但我仍然得到 'wanted but not invoked error' ,但是当我调用 r.getPrice() 时,测试通过了,这很奇怪,因为我认为间谍对象应该捕获与真实对象的交互。

因此,通过查看您的问题和评论,我建议您采取一些措施来推动这一进程。

因此,在没有看到完整代码的情况下,我不能 100% 确定这是否返回了预期的 Recipe[]

public synchronized Recipe[] getRecipes() {
    return recipeBook.getRecipes();
}

您应该将模拟的 recipeBookStub 注入您的 CoffeeMaker。

通常在以 TDD 风格编写代码时,我们从最基本的情况开始,在这种情况下,我会尝试该方法,直到 oyu 可以让您的方法通过:

public int makeCoffee(int recipeToPurchase, int amtPaid) { 
   getRecipes()[recipeToPurchase]getPrice();
   return 25;
}

另一个好的做法是在测试中使用尽可能少的逻辑。

而是:

Recipe r = spy(stubRecipies[0]);

尝试:

Recipe r = spy(recipe1);

更重要的是,CoffeeMaker 中未使用侦测对象:

Recipe r = spy(stubRecipies[0]);

r 是模拟对象,与数组中的对象不同,您可以通过以下方式快速证明这一点:

Assert.assertEquals(stubRecipies[0], r);
Assert.assertTrue(stubRecipies[0]== r);

assertTrue 将失败,这意味着 stubRecipies[0] 与间谍 (r) 不是同一个对象

如果您将数组中的第一个索引设置为等于您的间谍对象,您可能会发现效果更好