13

我想测试我班级的 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()

但我得到了同样的结果。

4

3 回答 3

14

即使超出了Mockito 的限制,模拟对象使用真实方法也没有多大意义equals,如果没有其他原因,equals 方法几乎总是使用字段,并且模拟对象从不运行它们的任何构造函数或字段初始值设定项。

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

您有一些解决方法:

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

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

  • 创建一个equivalentTo方法,它与equals(例如,因此对 Map 或 Set 对象没有那么有用)但具有您可以自己定义的可模拟语义。

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

  • 提取一个测试相等性的对象,然后模拟它。你也可以在那里使用GuavaEquivalence,或者Comparator你测试的地方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();
    }
    

请注意,另一种潜在的解决方法——<a href="http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html" rel="noreferrer">监视现有实例——也将重新定义equals并且hashCode不会在这里帮助你。

于 2013-11-04T23:30:49.597 回答
3

如果你想测试真实 equals的,那么你需要创建一个真实的对象并调用equals它的方法。我不确定你为什么使用模拟。

于 2013-11-04T22:58:48.723 回答
0

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

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

对你来说是真实的。如果你想虚假使用

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

于 2015-04-01T22:24:38.900 回答