gpt4 book ai didi

java - 如何计算使用 Junit 和 Mockito 调用某个方法的次数?

转载 作者:太空宇宙 更新时间:2023-11-04 10:15:14 25 4
gpt4 key购买 nike

我想在 ProductService 中测试这个方法:

@Override
public void validateUpdate(Product product, Product modifiedProduct, List<FieldError> errors) throws AppException {
if(modifiedProduct == null || product == null) {
addError(errors, "product", "Product cannot be null");
}else {
validateName(modifiedProduct.getName(), errors);
validateShortDescription(modifiedProduct.getShortDescription(), errors);
validateDescription(modifiedProduct.getDescription(), errors);
validateRegularPriceAndPromotionprice(modifiedProduct.getRegularPrice(), modifiedProduct.getPromotionPrice(), errors);
validateCategory(product.getCategory(), errors);
validateCategoryMatches(product.getCategory(), modifiedProduct.getCategory(), errors);
validateStore(product.getStore(), errors);
validateSku(modifiedProduct.getSku(), errors);
validateWeight(modifiedProduct.getWeight(), errors);
validateQuantityInStock(modifiedProduct.getQuantityInStock(), errors);
validateNotifyLowStock(modifiedProduct.getNotifyLowStock(), errors);
}
}

但我只想创建一个测试来验证是否所有方法都被调用。第一个是查看 addError 方法是否被调用一次:

@Test
public void testValidateUpdateProduct() {
ProductService productService = Mockito.mock(ProductService.class);
List<FieldError> errors = new ArrayList<FieldError>();
productService.validateUpdate(null, null, errors);
Mockito.verify(productService, Mockito.times(1)).addError(errors, "product", "Product cannot be null");
}

但后来我得到:

Wanted but not invoked:
productService.addError(
[],
"product",
"Product cannot be null"
);
-> at ca.edooby.edoobyapi.service.ProductServiceTest.testValidateUpdateProduct2(ProductServiceTest.java:1022)

However, there was exactly 1 interaction with this mock:
productService.validateUpdate(
ca.edooby.edoobyapi.model.Product@d2ca3a9,
ca.edooby.edoobyapi.model.Product@2b26d289,
[]
);

最佳答案

您似乎正在尝试验证模拟对象的行为。有几个原因可以解释为什么这是一个坏主意:

  1. 默认情况下,mockito 会将所有对实际方法的调用替换为 stub (不执行任何操作)
  2. 您的测试与类的内部实现高度耦合
  3. 调用的所有较小的验证方法都必须放宽可见性级别(至少到包私有(private))才能正常工作
  4. 它表明该类具有多种职责 - 理想情况下,您将有许多较小的 validator ,然后分别进行测试,然后您可以通过您喜欢的任何方法对组合 validator 进行单元测试(然后您可以完全删除子 validator )。

尽管如此,您尝试做的事情是可行的。我将其称为半模拟方法,如上所述 - 这是一种反模式。

为了简单起见,我们假设我们有一个这样的类:

public class Baz {
public void foo() {
bar();
}

public void bar() {
// stuff
}
}

foo 相当于您的 validateUpdate 方法,而 bar 相当于从那里调用的几乎所有其他 validator 方法。

测试将从配置半模拟开始:

    Baz baz = mock(Baz.class); 
doCallRealMethod().when(baz).foo();

这解决了测试的核心问题 - 它实际上并没有调用原始的 validateUpdate 方法,因为默认情况下,mockito 会 stub 所有方法(它们不会被调用)。

从那时起,测试将照常进行:

    baz.foo();
verify(baz).bar();

一切都过去了。再说一次,我不是测试者教皇莫基乌斯三世(Pope Mockius III),他不是某种权威,但一般来说你应该:

  • 坚持检查代码的输入和输出(它不会让您与实现有太多联系)
  • 如果您必须模拟/ stub 内容,请避免对被测系统执行此操作 - 这表明设计存在问题,并且该类可以进一步分解

希望有帮助。

关于java - 如何计算使用 Junit 和 Mockito 调用某个方法的次数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51801682/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com