Как вы издеваетесь над одиночной зависимостью в JMockit? - PullRequest
0 голосов
/ 26 января 2019

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

Одной из зависимостей является синглтон, созданный не для создания чего-либо, кроме самого себя. Как я понял (я новичок в JMockit), когда класс аннотируется @Mocked, все его методы и конструкторы подвергаются насмешкам. Документация JMockit :

Существуют три разные аннотации-насмешки, которые мы можем использовать при объявлении фиктивных полей и параметров: @Mocked, который будет насмехаться над всеми методами и конструкторами на всех существующих и будущих экземплярах макетируемого класса

Однако я заметил (с помощью точки останова), что конструктор реального класса вызывается и не может получить доступ к датчику, что приводит к сбою тестов.

Вот соответствующая часть синглтона, который я пытаюсь высмеять. Обратите внимание, что я не могу изменить этот класс:

public class DriverStation() {
    // This line in particular is an issue.
    private static DriverStation currentInstance = new DriverStation();

    public static DriverStation getInstance() {
        return DriverStation.instance;
    }

    private DriverStation() {
        // This constructor cannot be called during tests.
    }
}

А вот мой тестовый код:

public class BlingControllerTest {
    @Mocked
    private DriverStation station;

    @Tested
    private BlingController blingController;

    /**
     * Tests getting the robot's operation period while not in a real match.
     */
    @Test
    public void testGetOperationPeriodDuringRealMatch(@Mocked DriverStation station) {
        new Expectations(DriverStation.class) {{
            DriverStation.getInstance();
            result = station;

            station.isFMSAttached();
            result = true;

            station.isAutonomous();
            returns(true, false);
        }};
    }
}

Полный исходный код также доступен на GitHub

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

Stacktrace от запуска на travis-ci:

ca.team2706.frc.robot.commands.bling.BlingControllerTest > testGetOperationPeriodDuringRealMatch STANDARD_ERROR
    java.io.IOException: wpiHaljni could not be loaded from path or an embedded resource.
        attempted to load for platform /linux/x86-64/
        at edu.wpi.first.wpiutil.RuntimeLoader.loadLibrary(RuntimeLoader.java:79)
        at edu.wpi.first.hal.JNIWrapper.<clinit>(JNIWrapper.java:25)
        at edu.wpi.first.wpilibj.DriverStation.<init>(DriverStation.java:194)
        at edu.wpi.first.wpilibj.DriverStation.<clinit>(DriverStation.java:132)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:398)
        at mockit.internal.state.TestRun.ensureThatClassIsInitialized(TestRun.java:138)
        at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineType(BaseTypeRedefinition.java:65)
        at mockit.internal.expectations.mocking.TypeRedefinition.redefineType(TypeRedefinition.java:28)
        at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldType(FieldTypeRedefinitions.java:78)
        at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldType(FieldTypeRedefinitions.java:65)
        at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldTypes(FieldTypeRedefinitions.java:53)
        at mockit.internal.expectations.mocking.FieldTypeRedefinitions.<init>(FieldTypeRedefinitions.java:33)
        at mockit.integration.TestRunnerDecorator.handleMockFieldsForWholeTestClass(TestRunnerDecorator.java:142)
        at mockit.integration.TestRunnerDecorator.updateTestClassState(TestRunnerDecorator.java:40)

Любая помощь приветствуется.

...