Java I/O - 模拟 System.console() 的输入
Java I/O - Simulate input for System.console()
我正在为练习中创建的程序编写 JUnit。这意味着测试需要覆盖尽可能多的案例,我对程序中某些事情的实现方式没有任何影响。此外,该程序 运行 是一个无限循环,在某一时刻,它需要用户输入一些内容。
对于 JUnit 测试,我 运行 另一个 Thread
中的程序并在 JUnit Thread
.
中模拟用户输入
到目前为止,如果程序从 System.in
读取用户输入,一切正常,因为这个流很容易被替换。但也有可能程序与 System.console()
交互,目前我的测试无法涵盖。
是否可以模拟 System.console()
的输入,例如通过用另一个流替换其输入源?
(注意:JUnit 测试必须使用 Java6,没有任何外部库(JUnit 和 Hamcrest 除外)。)
编辑:很遗憾,我无法更改要测试的程序的 类。
我认为您需要为控制台创建一个抽象,如 this post 中所述。并在代码中使用这个抽象而不是 System.console()
。然后你可以在测试中模拟抽象 you 控件。
编辑:
另一个更复杂的解决方案是在JVM加载时修改System.console()
(或sun底层类)的字节码。这是通过提供您自己的 ClassLoader
实现来完成的,您可以找到有关如何执行此操作的信息。
我不确定你想去这个兔子洞...
在路上我可以想到使用模拟扫描仪 class。例如
int i = sc.nextInt();
现在将调用模拟实现
public void Scanner getScanner(){
}
// inject mock object for unit testing and in prod ,
real object with input stream from console
public void Scanner setScanner(Scanner scanner){
}
查看 JDK 源代码后,我发现 Console
class 正在从标准输入 (System.in
) 读取数据:
reader = new LineReader(StreamDecoder.forInputStreamReader(new FileInputStream(FileDescriptor.in), readLock, cs));
其中FileDescriptor.in
是指向真实标准输入(public static final FileDescriptor in = standardStream(0);
)的常量。
因此,即使您使用 System.setIn()
替换 System.in
,控制台 class 仍将使用真正的标准输入。
您唯一的选择是将 Console
对象替换为 mock。
我正在为练习中创建的程序编写 JUnit。这意味着测试需要覆盖尽可能多的案例,我对程序中某些事情的实现方式没有任何影响。此外,该程序 运行 是一个无限循环,在某一时刻,它需要用户输入一些内容。
对于 JUnit 测试,我 运行 另一个 Thread
中的程序并在 JUnit Thread
.
到目前为止,如果程序从 System.in
读取用户输入,一切正常,因为这个流很容易被替换。但也有可能程序与 System.console()
交互,目前我的测试无法涵盖。
是否可以模拟 System.console()
的输入,例如通过用另一个流替换其输入源?
(注意:JUnit 测试必须使用 Java6,没有任何外部库(JUnit 和 Hamcrest 除外)。)
编辑:很遗憾,我无法更改要测试的程序的 类。
我认为您需要为控制台创建一个抽象,如 this post 中所述。并在代码中使用这个抽象而不是 System.console()
。然后你可以在测试中模拟抽象 you 控件。
编辑:
另一个更复杂的解决方案是在JVM加载时修改System.console()
(或sun底层类)的字节码。这是通过提供您自己的 ClassLoader
实现来完成的,您可以找到有关如何执行此操作的信息。
我不确定你想去这个兔子洞...
在路上我可以想到使用模拟扫描仪 class。例如
int i = sc.nextInt();
现在将调用模拟实现
public void Scanner getScanner(){
}
// inject mock object for unit testing and in prod ,
real object with input stream from console
public void Scanner setScanner(Scanner scanner){
}
查看 JDK 源代码后,我发现 Console
class 正在从标准输入 (System.in
) 读取数据:
reader = new LineReader(StreamDecoder.forInputStreamReader(new FileInputStream(FileDescriptor.in), readLock, cs));
其中FileDescriptor.in
是指向真实标准输入(public static final FileDescriptor in = standardStream(0);
)的常量。
因此,即使您使用 System.setIn()
替换 System.in
,控制台 class 仍将使用真正的标准输入。
您唯一的选择是将 Console
对象替换为 mock。