как издеваться над вызовом kotlin.system.exitProcess - PullRequest
0 голосов
/ 19 декабря 2018

Я хочу протестировать некоторый код, который использует сторонний код, который вызывает kotlin.system.exitProcess(), определенный в стандартной библиотеке следующим образом:

@kotlin.internal.InlineOnly
public inline fun exitProcess(status: Int): Nothing {
    System.exit(status)
    throw RuntimeException("System.exit returned normally, while it was supposed to halt JVM.")
}

Когда вызывается exitProcess(), JVM останавливается и дальнейшее тестированиеневозможно.Мне не удалось издеваться над звонками на exitProcess() с помощью макета.Возможно ли это?

Некоторая дополнительная информация:

Сторонней библиотекой является Clikt (https://ajalt.github.io/clikt/), хорошая библиотека для создания интерфейса командной строки. Приложение Clikt анализирует командную строкуи завершается, если это не удается. Это может быть одной из редких причин, когда вызывается System.exit. Конечно, есть более тестируемые решения, но в любом случае, при работе со сторонними библиотеками, спорят, что можно сделать лучше в библиотека устарела.

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

Я также пытался смоделировать вызов System.exit() следующим образом: mockkStatic ("java.lang.System") every {System.exit (any ())} .throws (RuntimeException ("blubb")), который приводитк другой проблеме, так что все вызовы System затем высмеиваются:

io.mockk.MockKException: every/verify {} block were run several times. Recorded calls count differ between runs
Round 1: class java.lang.System.getProperty(kotlin.ignore.old.metadata), class java.lang.System.exit(-630127373)
Round 2: class java.lang.System.exit(158522875)

Как ни странно, мне удалось проверить это на Java с помощью jmockit, например:

public class MainTestJ {
    private ByteArrayOutputStream consoleOut;

    @BeforeEach
    public void mockConsole() {
        consoleOut = new ByteArrayOutputStream();
        System.setOut(new PrintStream(consoleOut));
    }

    @Test
    public void can_mock_exit() {
        new MockUp<System>() {
            @Mock
            public void exit(int exitCode) {
                System.out.println("exit called");
            }
        };
        assertThatThrownBy(() -> {
            new Main().main(new String[] { "--help" });
        }).isInstanceOf(RuntimeException.class);
        assertThat(consoleOut.toString()).startsWith("Usage: bla bla ...");
    }
}

1 Ответ

0 голосов
/ 19 декабря 2018

Я играл с этим некоторое время, пытаясь заставить его работать, но, к сожалению, это невозможно.Есть несколько трудностей с насмешкой над этой функцией;что это функция верхнего уровня и что она возвращает Nothing.Каждый из них может быть преодолен, но что делает невозможным то, что функция встроена .Встроенные функции kotlin не производят методы в байт-коде, это, как сказано в олове, встроено.Проблема в том, что Mockk и другие библиотеки-насмешки используют инструкции для байт-кода.Обратитесь к этой проблеме для получения дополнительной информации.

Ваша лучшая альтернатива - не пытаться смоделировать эту функцию вообще, а вместо этого смоделировать вызов в сторонней библиотеке, которую вы используете.В конце концов, вы не должны тестировать этот сторонний код, только свой собственный код.А еще лучше, может быть, вам следует искать альтернативную библиотеку.Как уже было сказано в комментариях, сторонняя библиотека не должна выходить из процесса, это следует оставить на усмотрение клиентского кода.

...