防止等于方法的存根

时间:2013-11-04 22:34:48

标签: methods mocking mockito equals stub

我想测试我的类'equals()方法,但Mockito似乎每次调用存根版本。我的测试如下;

PluginResourceAdapter adapter = mock (PluginResourceAdapter.class);
PluginResourceAdapter other = mock (PluginResourceAdapter.class);

when(adapter.getNumberOfEndpointActivation()).thenReturn(1);
when(other.getNumberOfEndpointActivation()).thenReturn(0);

boolean result = adapter.equals(other);
assertFalse(result);

我知道我不能存储equals方法,这意味着Mockito应该调用我的真实实现但不是。

我也试过这个:

when (adapter.equals(any()).thenCallRealMethod()

但我得到的结果相同。

3 个答案:

答案 0 :(得分:13)

即使超出Mockito's limitations,对于模拟对象使用真正的equals方法也没有多大意义,如果没有其他原因,等于方法几乎总是使用字段和模拟对象永远不要运行任何构造函数或字段初始化器。

另外,请注意您正在测试的内容:在Foo的测试中,理想情况下,您不应该模拟Foo,甚至要设置Foo进行比较。否则,很容易无意中测试Mockito的工作原理,而不是测试你自己组件的逻辑。

您有一些解决方法:

  • 正如Garrett Hall所提到的,创造真实的物体。这可能需要从使用它们的服务中分解出“数据对象”,并在使用真实数据对象时模拟服务。这可能是一个好主意。

  • 通过继承PluginResourceAdapter或在Mockito之外实现相关接口来创建手动模拟或伪造。这使您可以根据需要定义所有方法,包括equalshashCode

  • 创建一个equivalentTo方法,它与equals不同(例如,对于Map或Set对象不那么有用)但是你有可模糊的语义可以自己定义。

    这也可以让你通过模拟自由地测试equivalentTo,并且只需要equals委托给那个可能经过良好测试的实现。

  • 提取测试相等性的对象,并模拟它。您也可以使用Guava's EquivalenceComparator来测试a.compareTo(b) == 0

    class YourClass {
      class AdapterEquivalence {
        boolean adaptersAreEqual(
            PluginResourceAdapter a, PluginResourceAdapter b) {
          return a.equals(b);
        }
      }
    
      /** Visible for testing. Replace in tests. */
      AdapterEquivalence adapterEquivalence = new AdapterEquivalence();
    }
    

请注意,另一个可能的解决方法 - spying on existing instances - 也会redefine equals and hashCode,并且不会对您有所帮助。

答案 1 :(得分:2)

如果您想测试真实 equals,那么您需要创建一个真实的对象并在其上调用equals方法。我不确定你为什么要使用嘲笑。

答案 2 :(得分:2)

默认情况下,如果对象在内存中具有相同的地址,则equals()将返回true 所以

PluginResourceAdapter adapter; PluginResourceAdapter other; adapter = other = mock (PluginResourceAdapter.class);

返回true给你。如果您想要错误使用

PluginResourceAdapter adapter = mock (PluginResourceAdapter.class); PluginResourceAdapter other = mock (PluginResourceAdapter.class);