Java & Mockito - 将参数传递给方法并捕获结果



我正在尝试修复一些现有的 junit/mockito 测试,由于重写以使用 Dao's 而不得不更改这些测试。

所以我有这个论点俘虏:-

ArgumentCaptor<CustomerDao> customerDaoCaptor = ArgumentCaptor.forClass(CustomerDao.class);

我以前使用过这种方法来获取(客户(对象,以便我可以对其执行更多测试。我通常会这样使用它:-

verify(customerDao, times(1)).saveOrUpdate(customerDaoCaptor.capture());    

这样我就可以运行这样的测试:-

Customer customerActual = (Customer) customerDaoCaptor.getAllValues().get(0);
assertEquals("PRE", customerActual.getExistingCustomer());

但是,在这种情况下,我不是在调用 saveOrUpdate 方法(捕获者绑定到的方法(,而是另一个 Dao 方法,该方法将唯一键作为参数,最终使用 sql 更新客户记录 - 即它不使用父对象的 (Hibernate( saveOrUpdate 方法。

我知道我可以测试它的名字,例如:-

inOrder.verify(customerDao, times(1)).updateRegisterStatusToCurrentByCustomerNumber(CUSTOMER_NUMBER);

所以我试图以某种方式将俘虏分配/绑定到"更新注册状态..."。方法,但我似乎找不到一种方法来做到这一点,主要是因为该方法必须采用字符串参数,customer_number。

所以本质上我正在尝试这样做:-

inOrder.verify(customerDao, times(1)).updateRegisterStatusToCurrentByCustomerNumber(CUSTOMER_NUMBER).customerDaoCaptor.capture()

这显然是行不通的...

由于很多谷歌搜索对我没有帮助,我猜我做得完全错了。

更新 - @SpaceTrucker

我已经按照您的建议尝试了以下代码:-

CapturingMatcher<String> capturingMatcher = new CapturingMatcher<String>();
    verify(customerDao, times(1)).updateRegisterStatusToCurrentByCustomerNumber(
        argThat(
            org.hamcrest.Matchers.allOf(capturingMatcher, org.hamcrest.Matchers.notNullValue())
        )
    );
    List<String> values = capturingMatcher.getAllValues();

基于我的 Dao 实现:-

public void updateRegisterStatusToCurrentByCustomerNumber(String customerNumber)

它确实成功地通过了测试,因为它没有失败,但它并没有做我需要的一切。这里的理想目标是以某种方式获取一个代表更新的客户对象的对象 - 例如:-

Customer customerActual = (Customer) values.get(0);
assertEquals("value", customerActual.getExistingCustomer());

但是,值对象为空,在调试测试时,我可以确认正在调用有问题的方法。

如果我在这里错过了一些琐碎的事情,请提前道歉,再次感谢您的所有帮助!

这个问题似乎比最初想象的要困难得多。有关此内容的更多详细信息,请参见下文。

Mockito需要查看的Matcher实例必须实现CapturesArguments接口。因此,解决方案是实现一个AndMatcher,该将委托给其子匹配器并实现CapturesArguments。它将委派给所有在CapturesArguments.captureFrom(Object)时也实现CapturesArguments的子匹配器。请注意,CapturesArguments是一个Mockito内部接口。


以下解决方案不起作用,因为 Mockito 看到的Matcher实例没有实现CapturesArguments接口,因此不会将参数捕获委托给CapturingMatcher

ArgumentCaptor在内部使用CapturingMatcher。因此,您可以将Mockito.argThat与组合匹配器一起使用,该匹配器将由CapturingMatcher和您喜欢的任何其他匹配器组成。

例如给定接口

public interface ProductService {
    List<Product> getProductsForCategory(Category category);
}

然后我们可以执行以下操作:

import org.hamcrest.Matchers;
// ...    
CapturingMatcher<Category> capturingMatcher = new CapturingMatcher<Category>();
Mockito.verify(productService).getProductsForCategory(Mockito.argThat(Matchers.allOf(capturingMatcher, Matchers.notNullValue())));
List<Category> values = capturingMatcher.getAllValues();

您还可以使用capture方法实现自己的ArgumentCaptor,该方法将采用额外的匹配器实例。

你的问题并不完全清楚,但我从中得到了以下几点:

  1. 你有一个CustomerDao的模拟.
  2. 您的测试(间接(调用此模拟的 updateRegisterStatusToCurrentByCustomerNumber() 方法,向其传递String标识符。
  3. updateRegisterStatusToCurrentByCustomerNumber()在内部对Customer对象执行某些操作。
  4. 您希望测试有关相关对象Customer的内容。

如果这些是正确的,那么你对模拟的工作原理有一个根本性的误解。对Customer对象执行某些操作的内部代码?在此测试中,该代码不存在。它从未被召唤过。CustomerDao 的模拟版本通过简单地返回测试设置代码告诉它的内容来响应您的updateRegisterStatusToCurrentByCustomerNumber()调用,无论是null、精心制作的示例对象还是其他模拟。它从不调用实际的CustomerDao代码,因为模拟的全部意义在于使测试不依赖于该代码,以便该代码中的错误不会在整个依赖项树中级联测试失败。

为了测试CustomerDao.updateRegisterStatusToCurrentByCustomerNumber()的内部行为,你需要创建单独的测试,直接在非模拟CustomerDao上调用CustomerDao方法,其他一切都是模拟的。

相关内容

  • 没有找到相关文章

最新更新