转载若未授权删

码农家园

关于java:Mockito Mock一个叫两次的方法调用


javajunitmockitospringmockitounit-testing

Mockito Mock a method call called twice

我试图用mockito来模拟一个方法。 但是我注入模拟的类在调用两个相同类型的不同对象时调用该方法两次,但是根据对象中的值确定方法的输出。

所以,例如,如果我想嘲笑

1

public ArrayList<example> attemptToMock(testObject testing)

让sat类型testObject包含一个字符串值。

因此,如果testObject中的字符串值为"OK",那么attemptToMock应该输出一个包含两个对象的数组。 如果testObject字符串值为"NO",则发出的Array列表只有一个Object。

如何编写一个测试来处理一个调用,以便一个类可以在同一个方法中调用attemptToMock两次,并且我可以根据testObject中的值来模拟它的输出。 我可以模拟它发送不同的数组。


一些选择:

  • 覆盖对象上的equals和hashCode(TestObject)。这只有在对象上的所有值都是可预测的情况下才可行,并且可能比其他解决方案更有效,但如果您还需要编写equals和hashCode(例如,对于Map和Set行为),这是合理的解决方案。

    1
    2
    3

    // Mockito compares with objects' equals(Object) methods by default.
    when(collaborator.attemptToMock(object1)).thenReturn(array1);
    when(collaborator.attemptToMock(object2)).thenReturn(array2);

  • 写一个Hamcrest匹配器并使用它匹配数组。对于特定情况,这可以作为equals的紧凑模拟,如果您需要在许多测试中根据相同的值更改行为,则特别方便。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    public class IsATestObjectWithValue extends TypeSafeMatcher<TestObject> {
      private final String expectedValue;

      public IsATestObjectWithValue(String expectedValue) {
        super(TestObject.class);
        this.expectedValue = expectedValue;
      }

      @Override public void matchesSafely(TestObject object) {
        // object will never be null, but object.value might.
        return expectedValue.equals(object.value);
      }
    }

    现在您可以编写如上所述的等效匹配:

    1
    2
    3
    4

    when(collaborator.attemptToMock(argThat(new IsATestObjectWithValue("OK")))
        .thenReturn(array1);
    when(collaborator.attemptToMock(argThat(new IsATestObjectWithValue("NO")))
        .thenReturn(array2);

  • 使用答案,如wdf所述。匿名内部答案很常见且非常简洁,您可以访问所有参数。这对于一次性解决方案尤其有用,或者如果您希望在传入无效值(testObject.value)时显式地立即使测试失败。

  • 作为最后的手段,如果调用的顺序是可预测的,您可以按顺序返回多个值。

    1
    2
    3
    4

    when(collaborator.attemptToMock(any(TestObject.class)))
        .thenReturn(array1).thenReturn(array2);
    when(collaborator.attemptToMock(any(TestObject.class)))
        .thenReturn(array1, array2);  // equivalent

    无论参数如何,上述任何一行都将返回第一次调用的array1和第二次调用的array2以及之后的所有调用。这个解决方案比原始问题要脆弱得多 - 如果调用顺序发生变化,或者如果其中一个调用被删除或重复,它将失败 - 但如果测试非常紧凑,有时候这是最紧凑的解决方案临时或如果订单是绝对修复的。


您可以访问传递给模拟方法调用的参数,并使用Answer接口相应地改变返回值。请参阅此问题的答案以及答案的文档。

基本上,这里唯一的奇怪/非显而易见的事情是你必须将参数向下转换为你期望的类型。因此,在您的情况下,如果您正在模拟一个采用单个"TestObject"参数的方法,那么您必须在"回答"实现中执行类似的操作:

1
2
3
4
5
6
7

Object[] args = invocation.getArguments();
TestObject testObj = (TestObject) args[0];
if ("OK".equals(testObj.value)) {
  return new ArrayList(value1, value2);
} else if ("NO".equals(testObj.value)) {
  return new ArrayList(singleObject);
}


Copyright ©  码农家园 联系:ddyu2x@gmail.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值