如何使用mockito spy进行懒惰评估



我想使用mockito spy。

当我通过以下两种方式设置返回值时:

when(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user)).thenReturn(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user, fakeNowDate));
doReturn(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user, fakeNowDate)).when(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);

我看到回报值正在急切地评估

意思是当执行此"设置"行时。

我如何才能强迫间谍只按需评估回报值?

即满足"何时"条件。

更新

感谢@RobbyCornelissen,我已经尝试了这个代码:

    when(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user)).thenAnswer(new Answer() {
        public Object answer(InvocationOnMock invocation) {
            Object[] args = invocation.getArguments();
            ImagesSorter mock = (ImagesSorter)invocation.getMock();
            return mock.sortImages((List<Image>)args[0], (UserInfo)args[1], fakeNowDate);
        }
    });

但它没有帮助:

1) 立即调用"when"表达式。(不需要)

2) 最终回调没有被调用。

首先让我就部分mock向您发出警告,因为代码实际上就是这样做的,这是错误的设计。使用策略模式来组成受试者的行为可能更相关。Mockito团队(包括我)强烈建议尽可能远离部分模拟。

EDIT:我不知道代码,也不知道测试的确切组件,但据我所知,有一种类型负责对图像进行排序,我们称之为ImagesSorter

  1. 因此,第一种情况ImagesSorter是测试对象的依赖项,因此在这种情况下,只需存根ImagesSortermock即可。

  2. 然而,如果它是ImagesSorter本身在测试中,并且存根这个类的一个特殊方法被称为部分mock,那么这是完全错误的。它在测试中公开生产代码的内部。所以有几个解决方案。

    1. 正如答案中显示的代码片段显示的fakeDate一样,解决方案之一是不使用new Date()之类的东西,而是编写一个简单的类TimeSource,其唯一职责是提供日期。在试验中,该CCD_ 8的性能可以被忽略。

      一个更简单的解决方案是使用JodaTime,因为它提供了内置的功能。

    2. 如果测试的范围超出了更改日期的范围,那么ImagesSorter可能需要一种方法来配置其他对象。如何做到这一点的灵感可以从番石榴的缓存生成器中找到。如果配置非常简单,那么一个简单的构造函数就可以完成

      这可能看起来像:

      class ImagesSorter { 
          ImagesSorterAlso algo;
          ImagesSorter(ImagesSorterAlgo algo) { this.algo = algo; }
          Iterable sortImages(...) {
             algo.sort(...);
          }
      }
      interface ImagesSorterAlgo {
          Iterable sort(...);
      }
      

现在谈谈你的问题:

1) 立即调用"when"表达式。(不需要)

预计imagesSorterSpy是一个间谍,因此默认情况下它调用真实代码。相反,你应该使用替代的API,就像@RobbyCornelissen展示的一样。即

doAnswer(sortWithFakeDate()).when(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);
// with BDD aliases (BDDMockito) which I personnaly finds better
willAnswer(sortWithFakeDate()).given(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);
will(sortWithFakeDate()).given(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);

sortWithFakeDate()将是一个返回答案的静态工厂方法,因此代码读起来很好,可能在其他地方重复使用。

2) 最终回调没有被调用。

这个问题很可能是由于不平等的争论。您可能需要检查equals方法。或者使用any()匹配器放松存根。

我不知道您使用的参数和类的类型,所以我不能提供一个完整的示例,但您可以使用Answer<T>接口的回调进行存根:

Mockito.doAnswer(new Answer() {
    Object answer(InvocationOnMock invocation) {
         ImagesSorter mock = (ImagesSorter) invocation.getMock();
         Object[] args = invocation.getArguments();
         return mock.sortImages((List<Image>) args[0], (UserInfo) args[1],
                 fakeNowDate);
    }
}).when(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);

相关内容

  • 没有找到相关文章

最新更新