Как выполнить проверку конкретных экземпляров имитируемых классов с заданным конструктором в JMockit?

Я использовал JMockit для имитации зависимостей для робота (таких как датчики, джойстики и т. д.). Для одного из тестов моих классов мне нужно смоделировать два объекта джойстика.

В коде, который у меня есть, джойстики создаются так:

Joystick joystick1 = new Joystick(0);
Joystick joystick2 = new Joystick(1);

Я читал о том, как сопоставлять определенные экземпляры объектов в разделе сопоставления экземпляров в документацию JMockit.

Однако эти шаги, похоже, не работают для проверок (или, может быть, я делаю это неправильно), или они включают использование тега @Mocked в параметрах каждого метода тестирования, что было бы проблемой, учитывая тот факт, что я хочу, чтобы это поведение выполнялось для всего класса из нескольких тестов.

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

Поведение, к которому я стремлюсь, выглядит примерно так:

public class ClassUsingJoysticksTest {
    @Injectable
    private Joystick joystick1;

    @Injectable
    private Joystick joystick2;

    @Before
    public void setUp() {
        new Expectations() {{
            new Joystick(0);
            result = joystick1;

            new Joystick(1);
            result = joystick2;
        }};
    }

    @Test
    public void someTest() {
        ClassThatUsesJoysticks classThatUsesJoysticks = new ClassThatUsesJoysticks();
        classThatUsesJoysticks.doSomething();

        new Verifications() {{
            joystick1.setRumble(1D);
            joystick2.setRumble(2D);
        }};
    }
}

Соответствующая часть тестируемого класса:

public class ClassThatUsesJoysticks {
    public void doSomething() {
        Joystick joystick1 = OI.getInstance().getJoystick1(); // OI is our own class.
        Joystick joystick2 = OI.getInstance().getJoystick2();

        joystick1.setRumble(1);
        joystick2.setRumble(2);
    }
}

// OI class that we used to keep track of operator interface.
public class OI {
    private Joystick joystick1, joystick2;

    public OI() {
        joystick1 = new Joystick(0); // First joystick is always on port 0.
        joystick2 = new Joystick(1); // Next joystick is port 1.
    }

    public Joystick getJoystick1() {
        return joystick1;
    }

    public Joystick getJoystick2() {
        return joystick2;
    }
}

Возможно ли что-то подобное с помощью JMockit?

Если хотите, фактическую реализацию, которую я пытаюсь достичь (с плохой насмешкой над моей собственной кодовой базой), можно найти здесь.


person Kyle Anderson    schedule 05.02.2019    source источник
comment
Не могли бы вы показать свой тестируемый класс? То, что он получает их из другого класса, пахнет тем, что вы должны применить инверсию управления и ввести их туда.   -  person chrylis -cautiouslyoptimistic-    schedule 05.02.2019
comment
@chrylis добавил соответствующую часть тестируемого класса и класс, из которого он получает объекты джойстика.   -  person Kyle Anderson    schedule 05.02.2019
comment
Второй механизм, показанный в документации, должен работать... Вы пробовали это? ? И нет необходимости использовать тег @Mocked в параметрах каждого метода тестирования.   -  person Rogério    schedule 05.02.2019
comment
Не используйте OI.getInstance() именно по этой причине. Сделайте OI параметром конструктора ClassThatUsesJoysticks.   -  person chrylis -cautiouslyoptimistic-    schedule 05.02.2019
comment
@Rogério в первый раз, когда я попробовал, это не сработало, но я только что узнал, что это было не потому, что насмешка не выполнялась должным образом, а потому, что она работала только в первом тесте, который по какой-то причине был запущен. Я заставил его работать с парой настроек в аннотированном методе @Before.   -  person Kyle Anderson    schedule 07.02.2019


Ответы (1)


У меня это работает с текущей настройкой, как задокументировано.

public class ClassUsingJoysticksTest {
    @Mocked Joystick joystick1;
    @Mocked Joystick joystick2;

    @Before
    public void setUp() {
        new Expectations() {
            new Joystick(0);
            result = joystick1;

            new Joystick(1);
            result = joystick2;
        }
    }

    @Test
    public void testRumbles() {
        classThatUsesJoysticks.doSomething();

        new Verifications() {{
             joystick1.setRumble(1.0);
             joystick2.setRumble(1.0);
        }};
    }
}

Если вы хотите увидеть фактическую реализацию, код здесь.

person Kyle Anderson    schedule 07.02.2019