2013-04-06 2 views
2

Я пытаюсь выполнить тестирование основного метода, который вводит ввод с клавиатуры. Я знаю, что есть несколько вопросов о SO о тестировании ввода с клавиатуры и использовании System.setIn(...), но это работает только для первого ввода для меня.Тестирование нескольких последовательных клавиатурных входов

Мой код:

public class TestApp { 
    @Test 
    public void testMain() { 
     InputStream stdin = System.in; 
     try { 
      System.setIn(new ByteArrayInputStream("s\r\nx\r\n".getBytes())); 

      String args[] = {}; 
      App.main(args); 

      // TODO: verify that the output is what I expected it to be 
     } 
     catch(IOException e) { 
      assertTrue("Unexpected exception thrown: " + e.getMessage(), false); 
     } 
     finally { 
      System.setIn(stdin); 
     } 
    } 
} 

То, что я пытаюсь достичь для ввода «s», а затем «х» (два различных записей).

При нормальной работе программы он должен выводить данные после нажатия «s», а затем клавиши ввода, и выдает что-то еще после нажатия «x». Основной метод выглядит следующим образом:

class App { 
    public static void main(String[] args) throws IOException { 
     int choice; 
     do { 
      choice = getChar(); 
      switch(choice) { 
       case 's': 
        System.out.println("Text for S"); 
        break; 
       case 'x': 
        System.out.println("Exiting"); 
        break; 
      } 
     } while(choice != 'x'); 
    } 

    public static String getString() throws IOException { 
     InputStreamReader isr = new InputStreamReader(System.in); 
     BufferedReader br = new BufferedReader(isr); 
     String s = br.readLine(); 
     return s; 
    } 

    public static char getChar() throws IOException { 
     String s = getString(); 
     return s.charAt(0); 
    } 
} 

Примечание: Я знаю, что лучший способ достичь это, чтобы ввести в InputStream зависимость и использовать его вместо System.in, но я не могу изменить код. Это ограничение у меня есть, я не могу изменить main(), getString() или getChar() методов.

Когда я выполнить тест, это выход:

Текст для S

java.lang.NullPointerException
на App.getChar (tree.java:28)
на App.main (tree.java:7)
в TestApp.testMain (TestApp.java:15) < 23 внутренних вызовов>

Итак, похоже, что он получает первый вход ('s'), но не второй ...

Любая помощь очень ценится.

+0

Какой смысл тестировать модуль, если вы даже не можете исправить ошибки и проблемы с дизайном, обнаруженные модульным тестом? –

+0

Это задание, моя задача - обнаружить дефекты и написать отчет об этом. Исправление ошибок не является частью задания, и я не должен изменять код ... :( – satoshi

+1

Так что, похоже, вы нашли дефект: код не легко тестируется на единицу. –

ответ

1

getString метод создает новый BufferedReader при каждом вызове, который будет читать 8192 символов из System.in в свой буфер перед readLine возвращается. Это означает, что он читает «s», а также «x» при первом вызове, но только с использованием первой строки. Затем, по возвращении из метода, BufferedReader отбрасывается. При следующем вызове он создает новый экземпляр для поиска оставшихся символов, но, поскольку System.in уже разряжен, не находит его.

Само собой разумеется, что это ошибка.

Одним из возможных способов решения проблемы было бы создание манекена InputStream с прокладкой до отметки 8k после начальной и новой строки, за которой следуют «x» и «новая линия».

Вы также можете построить более сложный макет System.in в сочетании с макетом System.out и пополнить его дополнительным вводом при обнаружении вызова System.out.println.

Смежные вопросы