如何通过模拟自动测试控制台输入



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

我为控制台输入、输出创建了一个包装类,并尝试模拟它的行为

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

我正在使用莫克托。当我运行测试时,它会提示我从控制台输入输入。但是,如果我输入预期的名称,测试就会通过,我想让它自动进行,这样我就不必在测试运行时输入任何输入。提前谢谢。

请看一下这个例子:

@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());
   }
}
您需要将

模拟对象注入到underTest实例中。

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

它可能是类似于以下内容:

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

在这里:

ConsoleReaderWriter testReaderWriter = mock(ConsoleReaderWriter.class);

问题是:特定的testReaderWriter应该由被测试的对象使用。现在,您正在创建一个模拟对象,该对象与您打算验证的对象无关。因此,您可以遵循其他答案中给出的建议,并确保您的模拟实际传递给被测试的对象。

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

new InputStreamReader(System.in)

您正在基于固定输入创建读取器。别这样。

相反,例如,您可以将 InputStream 的实例传递给 ConsoleReaderWriter 对象。然后该流用于所有输入。然后你不需要模拟任何东西,你只需要准备一个具有固定内容的流,然后把它提供给你的测试对象。

另一种方法是弄乱 System.in,例如这里概述的。

相关内容

  • 没有找到相关文章

最新更新