JUnit test for System.out.println()

前端 未结 13 1890
广开言路
广开言路 2020-11-22 03:18

I need to write JUnit tests for an old application that\'s poorly designed and is writing a lot of error messages to standard output. When the getResponse(String reque

13条回答
  •  日久生厌
    2020-11-22 04:03

    Based on @dfa's answer and another answer that shows how to test System.in, I would like to share my solution to give an input to a program and test its output.

    As a reference, I use JUnit 4.12.

    Let's say we have this program that simply replicates input to output:

    import java.util.Scanner;
    
    public class SimpleProgram {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.print(scanner.next());
            scanner.close();
        }
    }
    

    To test it, we can use the following class:

    import static org.junit.Assert.*;
    
    import java.io.*;
    
    import org.junit.*;
    
    public class SimpleProgramTest {
        private final InputStream systemIn = System.in;
        private final PrintStream systemOut = System.out;
    
        private ByteArrayInputStream testIn;
        private ByteArrayOutputStream testOut;
    
        @Before
        public void setUpOutput() {
            testOut = new ByteArrayOutputStream();
            System.setOut(new PrintStream(testOut));
        }
    
        private void provideInput(String data) {
            testIn = new ByteArrayInputStream(data.getBytes());
            System.setIn(testIn);
        }
    
        private String getOutput() {
            return testOut.toString();
        }
    
        @After
        public void restoreSystemInputOutput() {
            System.setIn(systemIn);
            System.setOut(systemOut);
        }
    
        @Test
        public void testCase1() {
            final String testString = "Hello!";
            provideInput(testString);
    
            SimpleProgram.main(new String[0]);
    
            assertEquals(testString, getOutput());
        }
    }
    

    I won't explain much, because I believe the code is readable and I cited my sources.

    When JUnit runs testCase1(), it is going to call the helper methods in the order they appear:

    1. setUpOutput(), because of the @Before annotation
    2. provideInput(String data), called from testCase1()
    3. getOutput(), called from testCase1()
    4. restoreSystemInputOutput(), because of the @After annotation

    I didn't test System.err because I didn't need it, but it should be easy to implement, similar to testing System.out.

提交回复
热议问题