单元测试:验证对象传入仓库时,用verify(eq())还是ArgumentCaptor?
问题:
ArgumentCaptor 和 eq() 验证仓库方法参数,哪个更好? 我一直使用ArgumentCaptor来检查传入仓库save方法的对象,示例如下:
@Captor private ArgumentCaptor<Product> productCaptor; @Test void create() { //code omitted Product product = new Product(); product.setId(101L); product.setName("Laptop"); CommandResponse result = productService.create(request); verify(productRepository).save(productCaptor.capture()); Product capturedProduct = productCaptor.getValue(); verify(productRepository).save(eq(product)); assertEquals(capturedProduct.getId(), result.id()); assertEquals("Laptop", capturedProduct.getName()); // ... }
不过我最近看到一个示例,它似乎既检查save方法是否被调用,也验证传入的对象:
verify(productRepository).save(eq(product));
既然该语句既能验证productRepository.save()被调用,又能确认传入对象与product相等,那它是否比使用ArgumentCaptor更好?
两者各有适用场景,没有绝对的“更好”
直接用
eq()更简洁高效:如果你的测试只需要确认save方法被调用,且传入的对象和你预期的实例完全相等(前提是Product类正确实现了equals()和hashCode()方法),那一行verify(productRepository).save(eq(product))就足够完成验证。这种方式不用额外定义ArgumentCaptor变量,代码更精简,逻辑更直接。ArgumentCaptor适配更复杂的验证场景:当你需要对传入的对象做更多精细化操作时,它的灵活性就体现出来了:- 只需验证对象的部分属性(比如不关心自动生成的
id,只检查name、price等业务字段); - 要将捕获的对象与测试中的其他输出结果做关联断言(比如你示例里把捕获对象的
id和result.id()做对比); - 方法被调用多次时,可通过
productCaptor.getAllValues()获取所有传入参数,逐一验证每一次调用的参数是否符合预期。
- 只需验证对象的部分属性(比如不关心自动生成的
另外要注意:你示例里同时使用两种验证方式属于重复操作——verify(productRepository).save(productCaptor.capture())已经确认了save被调用一次,后续再执行verify(...)会导致测试失败(除非save确实被调用了两次),实际测试中二者选其一即可。
内容的提问来源于stack exchange,提问作者user21391503
相关产品推荐
相关产品推荐

