Как проверить код, зависящий от System.console с использованием JUnit? - PullRequest
0 голосов
/ 05 мая 2020

Я пишу простую программу, используя System.console, и я пишу для этого тест. Я использую maven, чтобы проверить это, и тест не проходит.

Полный код доступен по адресу https://github.com/hhimanshu/reflection-testing/tree/console-test

Ниже приведены некоторые дополнительные сведения

CommandLineApp. java

package com.bl.h2;

import java.io.Console;

public class CommandLineApp {
    public static void main(String[] args) {
        final Console c = System.console();
        if (c == null) {
            System.err.println("console not available");
            System.exit(1);
        }

        String userName = c.readLine("Enter your name: ");
        System.out.println("Hello " + userName);
    }
}

CommandLineTest. java

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CommandLineAppTest {
    private final ByteArrayOutputStream out = new ByteArrayOutputStream();
    private final PrintStream originalOut = System.out;

    @BeforeEach
    public void setStreams() {
        System.setOut(new PrintStream(out));
    }

    @AfterEach
    public void restoreInitialStreams() {
        System.setOut(originalOut);
    }

    @Test
    public void testInputOutput() {
        CommandLineApp.main(new String[]{});
        assertEquals("Enter your name: ", out.toString());
    }

Я запускаю mvn clean test и тест не проходит

[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.044 s - in com.bl.h2.AppTest
[INFO] Running com.bl.h2.CommandLineAppTest
console not available
[INFO] 

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.1:test (default-test) on project reflection-testing: There are test failures.
[ERROR] 
[ERROR] Please refer to /Users/hhimanshu/code/java/reflection-testing/target/surefire-reports for the individual test results.
[ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
[ERROR] The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /Users/hhimanshu/code/java/reflection-testing && /usr/local/Cellar/openjdk/13.0.2+8_2/libexec/openjdk.jdk/Contents/Home/bin/java -jar /Users/hhimanshu/code/java/reflection-testing/target/surefire/surefirebooter14077774838729856584.jar /Users/hhimanshu/code/java/reflection-testing/target/surefire 2020-05-04T15-50-24_446-jvmRun1 surefire18146927270810499563tmp surefire_03196121267245760589tmp
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR] Crashed tests:
[ERROR] com.bl.h2.CommandLineAppTest
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /Users/hhimanshu/code/java/reflection-testing && /usr/local/Cellar/openjdk/13.0.2+8_2/libexec/openjdk.jdk/Contents/Home/bin/java -jar /Users/hhimanshu/code/java/reflection-testing/target/surefire/surefirebooter14077774838729856584.jar /Users/hhimanshu/code/java/reflection-testing/target/surefire 2020-05-04T15-50-24_446-jvmRun1 surefire18146927270810499563tmp surefire_03196121267245760589tmp
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR] Crashed tests:
[ERROR] com.bl.h2.CommandLineAppTest
[ERROR]     at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:669)
[ERROR]     at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:282)
[ERROR]     at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:245)
[ERROR]     at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1183)
[ERROR]     at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1011)
[ERROR]     at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:857)
[ERROR]     at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
[ERROR]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
[ERROR]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
[ERROR]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
[ERROR]     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
[ERROR]     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
[ERROR]     at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
[ERROR]     at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
[ERROR]     at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
[ERROR]     at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
[ERROR]     at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
[ERROR]     at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
[ERROR]     at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
[ERROR]     at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
[ERROR]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR]     at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]     at java.base/java.lang.reflect.Method.invoke(Method.java:567)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
[ERROR] 
[ERROR] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

Как я могу протестировать этот фрагмент кода с использованием JUnit5?

1 Ответ

0 голосов
/ 11 июля 2020

Вам необходимо ввести Console в ваш App, чтобы отделить его от System, который нельзя удалить.

import java.io.Console;
final class App implements Runnable {
    private final Console console;

    @Override
    public void run() {
        final String pass = this.console.readLine("Your name: ");
        this.console.printf(
            "Hello %s",
            pass
        );
    }
    
    public static void main(final String... args) {
        new App(System.console()).run();
    }

}

Затем вы можете использовать jmockit для имитации финального класса Console:

import mockit.Expectations;
import mockit.Mocked;
import mockit.Verifications;
import org.junit.jupiter.api.Test;

final class AppTest {

    @Test
    void printsName(@Mocked final Console console) {
        new Expectations() {{
            console.readLine(withInstanceOf(String.class));
            result = "Jeff";
        }};
        new App(console).run();
        new Verifications() {{
            console.printf(anyString, "Jeff");
        }};
    }
}

Примечание: для работы jmockit вам понадобится javaagent

...