我需要用JUnit测试一个方法(也就是由他调用的方法)。问题是"父母"方法需要用户在代码行中间从键盘输入:输入不会传递给其他方法,而是在正在运行和被测试的同一个方法中处理。
我知道我可以用String input = "sampleString";
InputStream in = new ByteArrayInputStream(input.getBytes());
System.setIn(in);
assertEquals(sampleString, Obj.inputReader("sampleString"));
,但据我所知,这是不能做到的,因为如果代码如下:
public class MyClass{
public int readInt() {
Scanner scan = new Scanner(System.in);
System.out.print("Enter number: ");
int num = scan.nextInt();
scan.close();
return num;
}
}
@Test
public void testmethod() throws IOException {
MyClass myclass = new Myclass();
myclass.readInt();
String input = "4";
InputStream in = new ByteArrayInputStream(input.getBytes());
System.setIn(in);
assertEquals(4, Obj.inputReader(parseToInt("4")));
测试继续运行,因为没有接收到键盘输入,并且不可能到达下一行。
有谁知道一个方法或建议一个路径来完成它吗?
提前感谢大家!
首先你的测试是错误的。你叫
myclass.readInt();
但从不读取结果。但是回到你的问题。
你可以用mock来实现这一点,例如Mockito。
你可以模拟Scanner类和scan.nextInt();电话。
比如:如果有人调用"scan.nextInt()"只返回准备好的值。
Scanner listMock = Mockito.mock(Scanner.class);doReturn(4)当(listMock) .nextInt ();
您的测试没有使用readInt()
的结果,也没有收到任何输入,因为您在调用readInt()
之后设置了System.setIn(in);
。
class InputTest {
@Test
public void testMethod() throws IOException {
// arrange
String input = "4";
InputStream in = new ByteArrayInputStream(input.getBytes());
System.setIn(in);
// act
MyClass myclass = new MyClass();
int num = myclass.readInt();
// assert
assertEquals(4, num);
}
@Test
public void testMethodInject() throws IOException {
// arrange
String input = "4";
InputStream in = new ByteArrayInputStream(input.getBytes());
Scanner scanner = new Scanner(in);
// act
MyClass myclass = new MyClass();
int num = myclass.readIntInjected(scanner);
// assert
assertEquals(4, num);
}
}
如果你注入Scanner
对象而不是创建它,它可能更容易测试。
class MyClass {
public int readInt() {
Scanner scan = new Scanner(System.in);
System.out.print("Enter number: ");
int num = scan.nextInt();
scan.close();
return num;
}
// more easly testable
public int readIntInjected(Scanner scanner) {
System.out.print("Enter number: ");
int num = scanner.nextInt();
scanner.close();
return num;
}
}