EasyMock - поведение изменилось при вызове метода с разными сигнатурами

В настоящее время у меня есть модульный тест, который отлично работает с EasyMock 3.4, но когда я пытаюсь скомпилировать и запустить его с помощью EasyMock 4.0.2, я заметил странное поведение, которое я действительно не понимаю:

У меня есть класс с двумя методами, как показано ниже (обратите внимание на изменение подписи):

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 вызывается метод setAccess с Object в качестве второго аргумента, а в 4.0.2 вызывается метод setAccess с InterfaceA в качестве второго аргумента, выдавая java.lang.ClassCastException, поскольку интерфейсы не связаны. Единственное, что у них общего, это то, что они расширяют интерфейс Remote.

Если я просто использую реализацию InterfaceB вместо того, чтобы издеваться над ней, вызывается правильный метод setAccess:

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

Вот полный рабочий пример для воспроизведения поведения. Первый setAccess работает, а второй не работает. Оба отлично работают при работе на EasyMock 3.4:

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 {}
}

Я ищу помощь, чтобы понять, почему это происходит и что именно изменилось. Я не мог найти никаких вопросов, связанных с этим поведением.


person RKrum    schedule 23.08.2019    source источник


Ответы (1)


Это связано с 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));
person Henri    schedule 26.08.2019
comment
Спасибо за объяснение! - person RKrum; 29.08.2019