今天我写了一个键盘类的输入功能,这个类长这样,它继承自一个键盘接口。
public interface KeyBoard {
String input();
}
public class KeyBoardImpl implements KeyBoard {
@Override
public String input() {
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
return input;
}
}
为了测试这个类的输入功能,我写了这样一个测试用例,用的是junit
public class KeyBoardImplTest {
KeyBoard keyBoard = new KeyBoardImpl();
@Test
public void test() {
String input = keyBoard.input();
System.out.println(input);
}
}
但是我在运行该测试用例后,发现无法在控制台输入任何内容,程序停在那里不动了。
我尝试了一下在main函数里面写个用例,发现能够输入。
public class KeyBoardImpl implements KeyBoard {
@Override
public String input() {
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
return input;
}
public static void main(String[] args) {
KeyBoard keyBoard = new KeyBoardImpl();
String input = keyBoard.input();
System.out.printf(input);
}
}
这是为啥呢,经过网上搜索,我找到了解决方案,并且大致了解了原因: junit是用例自动化单元测试的,那么控制台输入这个人工操作就应该不会支持,解决方案如下
https://stackoverflow.com/questions/1647907/junit-how-to-simulate-system-in-testing
上面链接中得票最多的一条的基本做法是:把输入流redirect到字符串输入,把要输入的字符串写入,运行测试案例,再把输入流重新设置为控制台输入,我按照这种方法修改了测试用例:
public class KeyBoardImplTest {
KeyBoard keyBoard = new KeyBoardImpl();
@Test
public void testInput() throws Exception {
String data = "Hello, World!\r\n";
String input;
InputStream stdin = System.in;
try {
System.setIn(new ByteArrayInputStream(data.getBytes()));
input = keyBoard.input();
} finally {
System.setIn(stdin);
}
System.out.println("input is----" + input);
}
}
运行该测试用例,得到了希望的结果: