Как я могу автоматически протестировать ввод данных с консоли? - PullRequest
2 голосов
/ 10 апреля 2019

При попытке смоделировать консольный ввод, тест не работает так, как я ожидал

Я создал класс-оболочку для ввода, вывода и попытался смоделировать его поведение

public class ConsoleReaderWriter {

public void printLine(String message) {

    System.out.println(message);
}

public String readLine() {
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
    String result = "";
    try {
        result = bufferedReader.readLine();
    } catch (IOException e) {
        System.err.print(e);
    }
    return result;

}

}

// тестируемый метод

public String readPlayerName() {
    consoleReaderWriter.printLine("> What is your name?");
    String playerName = consoleReaderWriter.readLine();
    return playerName;
}

// моя попытка тестирования

@Test
public void testReadPlayerNameShouldReturnNameString() {
    String testName = "John Doe";

    ConsoleReaderWriter testReaderWriter = mock(ConsoleReaderWriter.class);

    when(testReaderWriter.readLine()).thenReturn("John Doe");

    assertEquals(testName, underTest.readPlayerName());
}

Я использую Mockito.Когда я запускаю тест, он предлагает мне ввести данные с консоли.Тест проходит, если я ввожу ожидаемое имя, однако я хотел бы сделать его автоматическим, чтобы мне не приходилось вводить какие-либо данные во время выполнения теста.Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 10 апреля 2019

Пожалуйста, посмотрите на пример:

@RunWith(MockitoJUnitRunner.class)
public class TestClass {
   @Mock
   ConsoleReaderWriter crw;

   @InjectMocks
   UnderTestClass underTest;

   //Some other fields

   @Test
   public void testReadPlayerNameShouldReturnNameString() {
      String testName = "John Doe";

      when(crw.readLine()).thenReturn("John Doe");

      assertEquals(testName, underTest.readPlayerName());
   }
}
1 голос
/ 10 апреля 2019

Вам нужно вставить ваш смоделированный объект в ваш экземпляр underTest.

В самом классе UnderTest убедитесь, что вы не используете 'new' для создания зависимости ConsoleReaderWriter, а вместо этого принимаете ее извне, например, с помощью конструктора agrument.

Itможет быть что-то вроде:

@Test
public void testReadPlayerNameShouldReturnNameString() {
    String testName = "John Doe";


    ConsoleReaderWriter testReaderWriter = mock(ConsoleReaderWriter.class);
    when(testReaderWriter.readLine()).thenReturn("John Doe");

    UnderTest underTest = new UnderTest(testReaderWriter);            
    assertEquals(testName, underTest.readPlayerName());
}
1 голос
/ 10 апреля 2019

Здесь:

ConsoleReaderWriter testReaderWriter = mock(ConsoleReaderWriter.class);

Дело в том, что конкретный testReaderWriter должен использоваться объектом при проверке .Прямо сейчас вы создаете фиктивный объект, который никак не связан с вашим объектом, который вы собираетесь проверять.Таким образом, вы можете следовать советам, данным в других ответах, и убедиться, что ваш макет фактически передан тестируемому объекту.

Но лучшим подходом будет: отсоединить ваш производственный кодот входа, который он использует.Ваши проблемы начинаются здесь:

new InputStreamReader(System.in)

Вы создаете считыватель на основе фиксированного ввода.Не делай этого.

Вместо этого вы можете, например, передать экземпляр InputStream в ваш объект ConsoleReaderWriter.И затем этот поток используется для всего ввода.Тогда вам не нужно ничего подделывать, вы просто подготавливаете поток с фиксированным контентом и передаете его тестируемому объекту.

Другой способ - связываться с System.in, как описано здесь например.

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