Methods 防止相等方法的存根

Methods 防止相等方法的存根,methods,mocking,mockito,equals,stub,Methods,Mocking,Mockito,Equals,Stub,我想测试我的类的equals()方法,但Mockito似乎每次都在调用存根版本。我的测试如下 PluginResourceAdapter adapter = mock (PluginResourceAdapter.class); PluginResourceAdapter other = mock (PluginResourceAdapter.class); when(adapter.getNumberOfEndpointActivation()).thenReturn(1); when(ot

我想测试我的类的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()
但是我得到了同样的结果。

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

甚至更重要的是,如果没有其他原因,equals方法几乎总是使用字段,并且被模拟的对象从不运行任何构造函数或字段初始值设定项,那么被模拟的对象使用真正的
equals
方法也没有多大意义

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

您有一些变通方法:

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

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

  • 创建一个
    equivalento
    方法,它与
    equivalento
    不同(因此对贴图或集合对象不太有用),但它具有可模仿的语义,您可以自己定义

    这还允许您使用mock自由地测试
    equaletto
    ,并简单地将
    equals
    委托给假定经过良好测试的实现

  • 提取一个测试相等性的对象,并模拟它。您也可以在那里使用,或者使用一个
    比较器
    ,在这里测试
    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();
    }
    
请注意,另一种可能的解决方法——在这方面也不会有帮助。

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

PluginResourceAdapter适配器;
插件资源适配器其他;
adapter=other=mock(PluginResourceAdapter.class)


回归真实的你。如果您想要错误,请使用

pluginresourcedapter adapter=mock(pluginresourcedapter.class);

PluginResourceAdapter other=mock(PluginResourceAdapter.class)

Mockito使用自己的实现自动覆盖
equals
,这样当它需要记录某个方法已被调用到mock时,就可以在其内部结构(
HashMap
s或
TreeMap
s)中找到mock。这是它工作方式的基础,这就是为什么它不允许您提供自己的
equals
。我使用了第二个选项,即@覆盖了模拟所需的方法,并使用了真正的objec.equals(对象)。Thanks@Jeff尽管这很常见:
如果没有其他原因,模拟对象使用实equals方法没有多大意义,equals方法几乎总是使用字段,并且模拟对象从不运行任何构造函数或字段初始值设定项
,equals实现可以自由地使用getter而不是字段。所以我不认为这是mockito不允许平等存根的理由/hashcode@Dhiraj或者,对于纯单例对象,它根本不能使用字段。即使在一些遥远的案例中,这可能是有意义的,我希望您同意,这些限制将使您很难将此案例优先于其他有用的开发。这似乎并没有回答最初的问题。