如何模拟影响对象的void返回方法

24

我正在为我的应用编写单元测试,我想知道Mockito框架是否可能影响传递给返回void的模拟类方法的对象。例如,调用一个被mock的验证类,它包含一个通过参数传递对象跟踪各种变化和元数据的方法。

public GetCartItemsOutput getCartItems(GetCartItemsInput getCartItemsInput) {
    CartItemsFilter cartItemsFilter = new CartItemsFilter();
    validator.validateCartItemsInput(getCartItemsInput, cartItemsFilter); ...

我对另一个测试模拟了验证器类,但是对于这个测试,我需要模拟对cartItemsFilter对象的更改,但我不知道该如何做。

3个回答

42
答案是可以的,你有两种基本方法可以做到这一点,取决于你测试的需求。
如果你只想测试与模拟对象的交互作用,你可以简单地使用verify()方法,以验证该void方法是否被调用。
如果你的测试确实需要修改传递给模拟对象的参数,你需要实现一个Answer编辑后的内容以显示正确的使用Answer与void方法
doAnswer(new Answer() {
    @Override
    Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        ((MyClass)args[0]).myClassSetMyField(NEW_VALUE);
        return null; // void method, so return null
    }
}).when(mock).someMethod();
在Java 8+中,可以使用lambda表达式来简化上述操作:
doAnswer(invocation-> {
    Object[] args = invocation.getArguments();
    ((MyClass)args[0]).myClassSetMyField(NEW_VALUE);
    return null;
}).when(mock).someMethod();

1
感谢您的帮助。我花了一些时间才理解"((MyClass)args[0]).myClassSetMyField(NEW_VALUE);",但最终我明白了这个方法的目的是设置我传递给模拟方法的参数。再次感谢。 - tamuren

5
为了补充Kevin Welker的回答,如果你的MyClass是自定义类,则需要在其中定义一个equals/hashcode方法,这样Mockito才能使用它来精确匹配方法调用。
在我的情况下,“MyClass”是在第三方API中的,所以我必须像下面这样使用“any”方法 -
 doAnswer(new Answer() {
    Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        ((MyClass)args[0]).myClassSetMyField(NEW_VALUE);
        return null; // void method, so return null
    }
}).when(mock).someMethod(any(MyClass.class));

-1

ArgumentCaptor 也许也能帮上忙。

这里有一个从这里找到的片段:

  ArgumentCaptor<GetCartItemsInput > argument = ArgumentCaptor.forClass(GetCartItemsInput .class);
  verify(mock).getCartItems(argument.capture());
  assertEquals(cartItemsFilter, argument.getValue());

2
这并不能解决提问者的问题,他需要实现一个答案。 - iwein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接