如何通过模拟自动对控制台输入进行测试?

时间:2019-04-10 11:50:20

标签: java junit mockito

当尝试模拟控制台输入时,测试的行为不符合我的预期

我为控制台输入,输出创建了包装器类,并尝试模拟其行为

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 个答案:

答案 0 :(得分:3)

请查看示例:

@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 :(得分:1)

这里:

ConsoleReaderWriter testReaderWriter = mock(ConsoleReaderWriter.class);

情况是:特定的testReaderWriter应该由受测对象 使用。现在,您正在创建一个模拟对象,该对象与要验证的对象没有任何关系。因此,您可以按照其他答案中的建议进行操作,并确保将 mock 实际传递给被测对象。

但是更好的方法是:将生产代码与其使用的输入分离。您的问题从这里开始:

new InputStreamReader(System.in)

您正在创建基于固定输入的阅读器。不要那样做

例如,您可以将InputStream的实例传递到ConsoleReaderWriter对象。然后将该流用于所有输入。然后,您无需进行任何模拟,只需准备具有固定内容的流,然后将其提供给被测对象即可。

另一种方法是弄乱System.in,例如概述为here

答案 2 :(得分:1)

您需要将模拟对象注入underTest实例。

在UnderTest类本身中,请确保您不使用“ new”来创建ConsoleReaderWriter依赖项,而是从外部(例如,使用构造函数)接受它。

可能与以下内容类似:

@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());
}