有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

模拟防止equals方法的存根

我想测试我的类的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) 个答案

  1. # 1 楼答案

    即使在Mockito's limitations之外,被模拟的对象使用真正的equals方法也没有多大意义,如果没有其他原因,equals方法几乎总是使用字段,并且被模拟的对象从不运行任何构造函数或字段初始值设定项

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

    您有一些变通方法:

    • 正如加勒特·霍尔所说,创造真实的物体。这可能需要将“数据对象”从使用它们的服务中分解出来,并在使用真实数据对象时模拟这些服务。总的来说,这可能是个好主意

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

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

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

    • 提取一个测试相等性的对象,并模拟它。您也可以在那里使用Guava's ^{},或者在测试a.compareTo(b) == 0的地方使用Comparator

      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 ^{} and ^{},在这里对您没有帮助

  2. # 2 楼答案

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

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

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

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

  3. # 3 楼答案

    如果您想测试realequals,那么您需要创建一个real对象,并对其调用equals方法。我不知道你为什么要用mock