【问题标题】:Test console output using JUnit使用 JUnit 测试控制台输出
【发布时间】:2014-12-11 23:18:31
【问题描述】:

我正在尝试使用 JUnit 测试另一个程序的控制台输出。我遵循了here中给出的答案

这是我的 JUnit 类

import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.junit.*;

public class MainTest {
        private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
        private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();

        @Before
        public void setup() {
                System.setOut(new PrintStream(outContent));
                System.setErr(new PrintStream(errContent));
        }

        @Test
        public void test01_initTest() {
                String[] arguments = {"a", "b"};
                Main.main(arguments);
                String expected = "hello";
                assertTrue(expected == outContent.toString());
        }

        @After
        public void cleanUpStreams() {
            System.setOut(null);
            System.setErr(null);
        }
}

当我在 eclipse 中运行这个程序时,我也看不到控制台输出并且测试运行没有结束。但是,如果我直接从 test01_initTest() 在控制台上打印输出,则测试通过。要检查 Main.main() 是否正在打印,我还尝试了以下代码,在这种情况下我确实看到了控制台输出

import static org.junit.Assert.*;
import org.junit.*;

public class MainTest {
        @Test
        public void test01_initTest() {
                String[] arguments = {"a", "b"};
                Main.main(arguments);
        }
}

我厌倦了很多事情,但我无法弄清楚我在这里做错了什么。谁能帮帮我。

【问题讨论】:

  • 你为什么使用assertTrue?使用 AssertEquals(expected, outContent.toString())。 == 没有做你认为的事情。
  • 您好 Falmarri,我也试过了,但结果是一样的。我在控制台上看不到任何输出,并且测试运行没有结束
  • 我们必须看到Main的代码。您不会在 Main 中调用 System.exit() 吗?
  • 等等,你为什么期待控制台输出?您正在将 stdout 和 stderr 设置为其他流。
  • 嘿 dkatzel,是的,我在我的程序中使用 System.exit()。是这个问题吗?

标签: java junit


【解决方案1】:

如果您正在测试的代码调用System.exit(),JUnit 将无法正常完成。

如果该主线程终止,JUnit 将挂起。

解决方法是使用SecurityManager 来防止调用System.exit()

在另一个 StackOverflow 答案中,我描述了如何编写这样的 SecurityManager:

Getting list of tests from JUnit command line

(此处复制代码以防万一)。

此 SecurityManager 将在调用 System.exit() 时抛出自定义 TriedToExitException 并保留退出代码,以便您可以捕获异常并测试是否使用了正确的退出代码。

/**
 * A special implementation of {@link SecurityManager}
 * that will throw a {@link TriedToExitException}
 * if {@link System#exit(int)} is called.
 * This is useful for testing main methods
 * without shutting
 * down the jvm running junit.
 * Tests can catch {@link TriedToExitException}
 * to figure out what exit code was set.
 */
public static final SecurityManager NON_EXITABLE_MANAGER = new SecurityManager(){

    @Override
    public void checkPermission(Permission perm) {
        //allow everything
    }
    /**
     * Throws a {@link TriedToExitException} instead of exiting.
     * <p/>
     * {@inheritDoc}
     */
    @Override
    public void checkExit(int status) {
        throw new TriedToExitException(status);
    }

};

public static final class TriedToExitException extends SecurityException{
    private static final long serialVersionUID = 1L;
    private final int exitCode;

    public TriedToExitException(int exitCode){
        this.exitCode=exitCode;
    }

    @Override
    public String getMessage() {
        return String.format("tried to System.exit(%d)",exitCode);
    }

    public int getExitCode() {
        return exitCode;
    }

然后在您的单元测试中,您将 SecurityManager 替换为我们停止调用退出的版本(并保存旧的 SecurityManager,以便我们可以在测试后恢复它)

private SecurityManager previousManager=null;


@Before
protected void replaceManager() throws Throwable {
    previousManager = System.getSecurityManager();
    System.setSecurityManager(NON_EXITABLE_MANAGER);
}

@After
protected void restoreManager() {
    System.setSecurityManager(previousManager);
}

 @Test
public void testCallToExit() throws IOException{

     try{
       //something that calls System.exit
        fail("should call exit");
     }catch(TriedToExitException e){
         //make sure we get correct exit code
         assertEquals(-1, e.getExitCode());

     }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-13
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多