繁体   English   中英

使用JUnit测试控制台输出

[英]Test console output using JUnit

我正在尝试使用JUnit测试另一个程序的控制台输出。 我按照这里给出的答案

这是我的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);
        }
}

我累了很多事情,但是我无法弄清楚我在做什么错。 有人可以帮我吗。

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

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

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

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

从JUnit命令行获取测试列表

(为防万一,此处复制的代码)。

调用System.exit()时,此SecurityManager将引发自定义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());

     }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM