我只有一个方法main。如何检查System.out.println()并使用JUnit替换Scanner以自动输入值?
附言:请提供一些解决方案。。。
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] arr = new int[4];
for (int i = 0; i < arr.length; i++) {
arr[i] = scanner.nextInt();
}
for (int i = 0; i < arr.length; i++) {
int res = 0;
int k = 0;
int num = arr[i];
/*.....*/
System.out.println(num);
}
}
理想情况下,提取尴尬的依赖项,以便在没有它们的情况下进行测试。将main
简单更改为:
public static void main(String[] args) {
doWork(new Scanner(System.in), System.out);
}
// TODO: Rename to something meaningful
public static void doWork(Scanner input, PrintStream output) {
// Remainder of code
}
(对于output
,考虑使用Writer
而不是PrintStream
。)
然后,您实际上不需要对main
进行单元测试,但您可以使用基于StringReader
的Scanner
测试doWork
,并基于StringWriter
测试输出,提供您想要的任何输入并检查输出。
我遇到了类似的问题,这就是我最终要做的。
首先,我建议按照@Jon Skeet的建议,创建一个单独的方法,而不是使用类的main(String[])
方法。
然后,您可以让该方法将InputStream
作为参数,然后在使用传递的InputStream
作为其源的方法中创建一个Scanner
对象。这样,当方法被调用时,您可以将任何InputStream
(如System.in
)传递给该方法(详细说明如下)。
package my.package;
import ...;
public class MyClass
{
public static void myMethod(InputStream inputStream)
{
Scanner inputScanner = new Scanner(inputStream);
// Do stuff with the Scanner such as...
String input = inputScanner.nextLine();
System.out.println("You inputted " + input);
}
}
现在,在您的生产源代码中,您可以调用myMethod
并将其作为参数System.in
传递给myMethod(System.in);
然后在单元测试中,您可以通过ByteArrayInputStream
:创建模拟输入值
package my.package;
import ...;
public class MyClassTest
{
@Test
void testMyMethod()
{
// Simulates a user inputting the string "Mock input" and hitting enter
assertDoesNotThrow(myMethod(new ByteArrayInputStream("Mock inputn".getBytes())));
}
}
瞧,你现在有了一种方法来传递你的方法mock输入,而且它总体上更模块化了。
我只想指出,在使用System.in
时,需要小心关闭它,在单元测试中,在使用输入流时,需要注意重用对同一InputStream
的引用,因为它的状态可以在不同的使用中持续存在。