Получил пользовательский ввод из цикла for в тесте JUnit, теперь как на самом деле проверить его вывод? - PullRequest
1 голос
/ 01 ноября 2019

Итак, предположим, у меня есть следующий класс с methodA ():

public class example {

public void methodA() {
    System.out.println("Enter in an integer for each step.\n");
    Scanner scan = new Scanner(System.in); 
    int currentStepCount = 0; 
    int totalStepCount = 0;

    for (int step = 10; step <= 16; step++) {
        if (step == 15)
            continue; // Skip fifteenth step

        System.out.println("\nStep " + step + ": ");
        currentStepCount = scan.nextInt();

        totalStepCount += currentStepCount;
    }

    System.out.println("\n\nAll steps have been taken in.\n");
    System.out.println("Total step count comes out to: " + totalStepCount + "\n"); 
    System.out.println("The last step count was " + currentStepCount + ". \n");
}
}

И у меня есть тест JUnit, который может имитировать ввод:

class junitTests {
private final ByteArrayOutputStream output = new ByteArrayOutputStream();

@Before
public void setUpStreams() {
    System.setOut(new PrintStream(output));
}
@Test
void testA() {
    example ex = new example();
    ByteArrayInputStream in1 = new ByteArrayInputStream("13\n13\n13\n13\n13\n13\n".getBytes());

    System.setIn(in1);
    ex.methodA();
    String out = output.toString(); 

    System.out.println(out); //This isn't in the final unit test implementation, 
                            //just for demonstrating my issue.
}
}

, но язастрял на том, как на самом деле проверить, является ли вывод правильный вывод. Когда я пытаюсь напечатать ByteArrayOutputStream output, он получается пустым, поэтому, когда я пытаюсь выполнить метод assertEquals, он всегда терпит неудачу. Как реально сделать так, чтобы вывод не всегда был пустым. Или, в более общем смысле, как вообще можно проверить вывод метода. Заранее спасибо!

Ответы [ 3 ]

1 голос
/ 02 ноября 2019

Последний System.out.println все еще использует замененный PrintStream, поэтому ваш выходной байтовый массив содержит две копии. Вы можете сохранить оригинал System.out и использовать его для печати на консоли.

    private final ByteArrayOutputStream output = new ByteArrayOutputStream();
    private final PrintStream stdout = System.out;
    private final InputStream stdin = System.in;

    @Before
    public void setUpStreams() {
        System.setOut(new PrintStream(output));
    }

    @After
    public void restoreStreams() {
        System.setIn(stdin);
        System.setOut(stdout);
    }

    @Test
    public void testA() {
        example ex = new example();
        ByteArrayInputStream in1 = new ByteArrayInputStream("13\n13\n13\n13\n13\n13\n".getBytes());
        System.setIn(in1);
        ex.methodA();
        String out = output.toString();
        stdout.println(out);
    }
1 голос
/ 02 ноября 2019

Поскольку это тест JUnit, вы должны проверить вывод, сделав некоторое утверждение о нем;например,

assertTrue(output.contains("Total step count comes out to: 15"));

, если 15 - правильный результат. Тем не менее, это плохой способ написания теста, потому что, если он потерпит неудачу, вы не знаете, каково было действительное количество шагов (вместо 15).

Лучше написать свой метод так, чтобы он возвращалколичество шагов (или что вы хотите проверить), а затем используйте assertEquals, чтобы сделать утверждение о его значении. Таким образом, вам не нужно перенаправлять System.out для проверки результатов. А еще лучше, напишите свой метод, чтобы брать числа из массива, чтобы вам не нужно было перенаправлять System.in.

Тем не менее, если вы просто хотите увидеть распечатанный вывод метода, тогда зачемперенаправить System.out в первую очередь? Вы можете просто позволить методу напечатать то, что он печатает.

0 голосов
/ 02 ноября 2019

Я думаю, что лучшим долгосрочным решением проблемы является использование внедрения зависимостей. boot-and-bonnet прав, что вы не видите вывод, потому что вы перезаписали поток System.out. Чтобы избежать необходимости переопределять поток System.out, вы можете изменить метод, чтобы можно было передавать поток, в который можно записывать.

public static void methodA(PrintStream out) {
    out.println("Enter in an integer for each step.\n");
    Scanner scan = new Scanner(System.in);
    int currentStepCount = 0;
    int totalStepCount = 0;

    for (int step = 10; step <= 16; step++) {
        if (step == 15)
            continue; // Skip fifteenth step

        out.println("\nStep " + step + ": ");
        currentStepCount = scan.nextInt();

        totalStepCount += currentStepCount;
    }

    out.println("\n\nAll steps have been taken in.\n");
    out.println("Total step count comes out to: " + totalStepCount + "\n");
    out.println("The last step count was " + currentStepCount + ". \n");
}

Затем вы вызываете methodA следующим образом

ByteArrayOutputStream output = new ByteArrayOutputStream();
PrintStream out = new PrintStream(output);
methodA(out);

И теперь вы можете сделать это

System.out.println(output.toString());

Вы также можете запускать любые необходимые утверждения для этого ByteArrayOutputStream,

Наконец, в вашем коде, когда вы запускаете метод вне модульного теста, вы бы назвали его следующим образом

methodA(System.out);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...