防止等于方法的存根

SJu*_*ejo 10 methods equals mocking stub mockito

我想测试我的类'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);
Run Code Online (Sandbox Code Playgroud)

我知道我不能存在equals方法,这意味着Mockito应该调用我真正的实现,但事实并非如此.

我也试过这个:

when (adapter.equals(any()).thenCallRealMethod()
Run Code Online (Sandbox Code Playgroud)

但我得到了相同的结果.

Jef*_*ica 13

即使超出Mockito的限制,对于模拟对象使用真实equals方法也没有多大意义,如果没有其他原因,那么等于方法几乎总是使用字段,并且模拟对象永远不会运行任何构造函数或字段初始化器.

另外,要注意你正在测试的内容:在测试中Foo,理想情况下你应该永远不要嘲笑Foo,甚至设置一个Foo比较.否则,很容易无意中测试Mockito的工作原理,而不是测试你自己组件的逻辑.

你有一些解决方法:

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

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

  • 创建一个equivalentTo方法,该方法与equals(例如,对Map或Set对象不一样有用)但是具有可以自己定义的可模拟语义.

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

  • 提取测试相等性的对象,然后模拟它.您也可以Equivalence那里使用Guava,或者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();
    }
    
    Run Code Online (Sandbox Code Playgroud)

请注意,另一个潜在的解决方法 - 监视现有实例 - 也将重新定义equals,hashCode并且在此不会对您有所帮助.