Mockito的inOrder()和集合/映射



我有以下情况:我的类保留了两个对象的标识集。

集合逐渐填充了一些实例,在测试用例中,它们填充了mock。

然后,我的类有一个调用,它对一个集合的内容执行某些操作,然后再对另一集合的内容进行操作。这就是我正在测试的呼叫。

处理集合的顺序很重要。在集合中处理单个objecst的顺序并不重要,事实上,它取决于如何将身份哈希分配给集合中的mock。

所以在我的情况下,我有一个偏序:所有这些对象都必须在任何一个对象之前处理。

问题是,我如何用Mockito来表达它?inOrder()会崩溃,因为我必须指定对象的确切顺序,而这不是恒定的。

为了讨论在使用Mockito.inOrder时如何处理集合和地图,我们必须根据区分4种情况

  • 集合或映射是输入的还是在方法内部创建的(输入意味着它是通过方法参数、类变量访问的,或者是通过可以存根的方法调用返回的)
  • 集合或映射是否在方法内部被访问或迭代(或来自同一类的另一个方法或被调用的超类,因此无法存根)

这导致了4种组合或4种可能的情况。

  1. 集合或映射是正在测试的方法的输入参数,该方法将其传递给另一个方法或返回它,但不接触它。在这种情况下,只需模拟集合或映射即可。没有问题。

  2. 集合或映射是正在测试的方法的输入参数,该方法访问(或迭代)它。在这种情况下,您将创建一个包含一个或多个mock的集合或集合。在这种情况下,您永远不应该模拟集合或映射本身,因为在使用for循环或流对其进行迭代时,您不知道调用了哪些方法,并且需要对其进行存根处理(这取决于JRE的实现!)。因为在调用方法之前必须自己创建它,所以您可以决定要使用什么实现。如果它包含2个或多个模拟对象,或者正在测试的方法向其中添加对象,则创建有序集合或映射。如果该方法不应该修改它,而只应该读取它,那么创建一个不可修改的集合或映射。我喜欢在测试中使用Collections.singleton、Collections.singletonList和Arrays.asList。

  3. 被测试的方法创建并填充集合,但不访问或迭代它。如果该方法将对象添加到集合或映射中,这些对象作为参数传入,然后将集合或映射传递给另一个映射或返回,则没有问题。在这种情况下,不存在依赖于迭代顺序的要验证的调用。您只需要在之后断言它的内容(当返回时,或者如果没有返回但传递给另一个方法,则使用captor)。

  4. 正在测试的方法创建并填充集合,并访问或迭代它。当该方法创建集合或映射并将mock添加到其中,然后对其进行迭代并对这些mock执行操作时,如果您使用inOrder并且集合或映射未排序,则确实存在问题。在这种情况下,您应该尝试将该方法拆分为两个方法:一个方法创建并填充集合或映射(在情况3中结束,它可以是工厂类中的工厂方法),另一个方法访问或迭代它(在情况2中结束)。只需创建一个工厂方法并从现有方法中调用它就足以解决问题。

当包含正在测试的方法的类具有作为类变量的集合或映射时,如果方法访问或修改它,则可以将其视为方法的输入;如果方法设置了它,则将其视作为输出。但是,如果它是一个没有setter或getter的私有或受保护类变量,那么在调用方法之前,您可能需要使用反射用mock或包含一个或多个mock的集合或映射来设置它,或者在调用方法之后获取并验证它。

相关内容

  • 没有找到相关文章

最新更新