EasyMock - 调用具有不同签名的方法时行为发生变化

EasyMock - Behavior changed when invoking method with different signatures

我目前有一个单元测试 运行 使用 EasyMock 3.4 没问题,但是当我尝试使用 EasyMock 4.0.2 编译并 运行 它时,我注意到一个我不知道的奇怪行为不太懂:

我有一个 class 有两种方法如下(注意签名更改):

public TestAccessSource setAccess(Class<?> clazz, Object access) {
    return setAccess(clazz.getName(), access);
}

public TestAccessSource setAccess(Class<?> clazz, InterfaceA access) {
    return setAccess(clazz, (Object) access);
}

我在我的单元测试中调用 setAccess 方法,如下所示:

testSources.setAccess(InterfaceB.class, EasyMock.createNiceMock(InterfaceB.class));

在 3.4 中调用了以 Object 作为第二个参数的 setAccess 方法,在 4.0.2 中调用了以 InterfaceA 作为第二个参数的 setAccess 方法,抛出一个 java.lang.ClassCastException,因为接口不相关 - 它们唯一的共同点是它们扩展了 Remote 接口。

如果我只是使用 InterfaceB 的实现而不是模拟它,则会调用正确的 setAccess 方法:

testSources.setAccess(InterfaceB.class, new InterfaceB(){});

这是重现该行为的完整工作示例。第一个 setAccess 有效,但第二个失败。在 EasyMock 3.4 上 运行ning 时两者都工作正常:

public class TestEasyMockBehavior {

    public static void main(String[] args) {
        TestAccessSource testSources = new TestAccessSource();
        testSources.setAccess(InterfaceB.class, new InterfaceB(){});
        testSources.setAccess(InterfaceB.class, EasyMock.createNiceMock(InterfaceB.class));
    }

    public static class TestAccessSource {
        public TestAccessSource setAccess(Class<?> clazz, Object access) {
            return setAccess(clazz.getName(), access);
        }

        public TestAccessSource setAccess(Class<?> clazz, InterfaceA access) {
            return setAccess(clazz, (Object) access);
        }

        public TestAccessSource setAccess(String key, Object access) {
            System.out.println(key + " - " + access.getClass().getName());
            return this;
        }
    }

    public interface InterfaceA extends Remote {}

    public interface InterfaceB extends Remote {}
}

我正在寻求一些帮助,以了解发生这种情况的原因以及究竟发生了什么变化。我找不到与此行为相关的任何问题。

它与 EasyMock 4 相关,而不是 Java 11。确实,我更改了 EasyMock 4 的类型。之前是 T mock(Class<T>)。这真的很烦人,因为一旦你想做 List<String> list = (List) mock(List.class) 你就会收到警告。

所以我决定输入 T mock(Class<?>)。问题解决,类型推断。

缺点是在某些情况下无法推断,或者在极少数情况下无法正确推断。但是根据我的说法,这些情况是例外的,因为通常您将模拟分配给一个变量,以便能够记录东西然后重放。

要解决您的问题,您有两个解决方案:

  1. testSources.setAccess(InterfaceB.class, (InterfaceB) mock(InterfaceB.class));
  2. testSources.setAccess(InterfaceB.class, EasyMock.<InterfaceB>mock(InterfaceB.class));