尝试模拟控制台输入时,测试的行为不符合我的预期
我为控制台输入、输出创建了一个包装类,并尝试模拟它的行为
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,例如这里概述的。