我被要求在从命令行运行和操作的旧Java应用程序中引入单元测试.基本上主循环打印出一个菜单,用户输入一些内容并显示更多数据.
此Main类说明了应用程序的工作原理.
public class Main{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
public static void main(String argv[]) throws IOException{
while (true) {
char input = (char) reader.read();
if(input == 'x'){
return;
}
System.out.println(input);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我希望我的测试方法看起来像这样
public void testCaseOne(){
Main.main();
String result = "";
result = sendInput("1");
assertEqual(result, "1");
result = sendInput("x");
assertEqual(result,"");
}
Run Code Online (Sandbox Code Playgroud)
我知道System.setOut()和System.setIn()方法,但我无法找到一种方法使该System.setIn()方法在此上下文中工作,因为该reader.read()方法阻止了我的线程.
我的测试设计错了吗?有没有办法设计sendInput()方法来通过阻塞reader.read()调用?
我建议重构代码以允许注入输入/输出流,然后你可以模拟它们.如果你想把它变成类似的东西
public class Main{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
public static void main(String argv[]) throws IOException{
new YourClass(reader,System.out).run();
}
}
public class YourClass { // I don't know what your class is actually doing, but name it something appropriate
private final InputReader reader;
private final PrintStream output;
public YourClass(InputReader reader, PrintStream output) {
this.reader = reader;
this.output = ouptut;
}
public void run() {
while (true) {
char input = (char) reader.read();
if(input == 'x')
return;
output.println(input);
}
}
Run Code Online (Sandbox Code Playgroud)
这个设计做了两件事:
它需要你的主类逻辑.通常,main方法实际上仅用于启动应用程序.
它YourClass更容易进行单元测试.在测试中,您可以简单地模拟输入/输出.
编辑:更新此重构如何帮助阻止IO问题
通过如上所示使读取器/输出可注入,您实际上不需要使用真正的System.in和System.out - 您可以使用模拟.这消除了实际具有阻塞读取的需要.
public void testCaseOne(){
// pseudocode for the mock - this will vary depending on your mock framework
InputReader reader = createMock(InputReader);
// the first time you read it will be a "1", the next time it will be an "x"
expect(reader.read()).andReturn("1");
expect(reader.read()).andReturn("x");
PrintStream stream = createMock(PrintStream);
// only expect the "1" to get written. the "x" is the exit signal
expect(stream.println("1"));
new YourClass(reader,stream).run();
verifyMocks();
}
Run Code Online (Sandbox Code Playgroud)