如何使用 JUnit 在 Java 中测试简单的命令行应用程序
How to test a simple command line application in Java using JUnit
我如何使用 JUnit 测试我的简单主方法命令行 class,它使用 Scanner 从 system.in 读取并打印到 system.out。
import java.util.Scanner;
public class SimpleMainCmdApplication {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
System.out.println(scanner.next());
}
}
这是一个非常具体的用例,我正在做一门数据结构和算法课程,要求参与者上传一个 *.java 文件,其中的主要方法是从 System.in 读取(使用 Scanner) 并输出 System.out 的答案。当您上传代码时,网站会构建并运行应用程序,并测试和衡量算法的性能。
我想要一种模拟这种情况的方法,这样我就可以使用 JUnit 编写简单的集成测试,作为对每个任务采用 TDD 方法的一部分。其他堆栈溢出线程上有一些有用的指针可以提供帮助,但没有满足全部要求。
为了解决这个问题,我创建了一个私有方法,我可以从中传递命令行输入和主要方法的名称 class 我想用反射调用。然后我可以将标准的 hamcrest macthers 应用于输出。
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import org.junit.Before;
import org.junit.Test;
public class MainCmdTest {
private ByteArrayOutputStream byteArrayOutputStream;
private PrintStream console;
@Before
public void setup() {
byteArrayOutputStream = new ByteArrayOutputStream();
console = System.out;
}
@Test
public void shouldPrintTest() throws Exception {
runTest("test", "SimpleMainCmdApplication");
assertThat(byteArrayOutputStream.toString(), is("test\n"));
}
private void runTest(final String data, final String className) throws Exception {
final InputStream input = new ByteArrayInputStream(data.getBytes("UTF-8"));
final InputStream old = System.in;
try {
System.setOut(new PrintStream(byteArrayOutputStream));
System.setIn(input);
final Class<?> cls = Class.forName(className);
final Method meth = cls.getDeclaredMethod("main", String[].class);
final String[] params = new String[]{};
meth.invoke(null, (Object) params);
} finally {
System.setOut(console);
System.setIn(old);
}
}
}
在实际实施中,我还测量了执行代码所需的时间,并且能够设置阈值限制以进行测试。
我如何使用 JUnit 测试我的简单主方法命令行 class,它使用 Scanner 从 system.in 读取并打印到 system.out。
import java.util.Scanner;
public class SimpleMainCmdApplication {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
System.out.println(scanner.next());
}
}
这是一个非常具体的用例,我正在做一门数据结构和算法课程,要求参与者上传一个 *.java 文件,其中的主要方法是从 System.in 读取(使用 Scanner) 并输出 System.out 的答案。当您上传代码时,网站会构建并运行应用程序,并测试和衡量算法的性能。
我想要一种模拟这种情况的方法,这样我就可以使用 JUnit 编写简单的集成测试,作为对每个任务采用 TDD 方法的一部分。其他堆栈溢出线程上有一些有用的指针可以提供帮助,但没有满足全部要求。
为了解决这个问题,我创建了一个私有方法,我可以从中传递命令行输入和主要方法的名称 class 我想用反射调用。然后我可以将标准的 hamcrest macthers 应用于输出。
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import org.junit.Before;
import org.junit.Test;
public class MainCmdTest {
private ByteArrayOutputStream byteArrayOutputStream;
private PrintStream console;
@Before
public void setup() {
byteArrayOutputStream = new ByteArrayOutputStream();
console = System.out;
}
@Test
public void shouldPrintTest() throws Exception {
runTest("test", "SimpleMainCmdApplication");
assertThat(byteArrayOutputStream.toString(), is("test\n"));
}
private void runTest(final String data, final String className) throws Exception {
final InputStream input = new ByteArrayInputStream(data.getBytes("UTF-8"));
final InputStream old = System.in;
try {
System.setOut(new PrintStream(byteArrayOutputStream));
System.setIn(input);
final Class<?> cls = Class.forName(className);
final Method meth = cls.getDeclaredMethod("main", String[].class);
final String[] params = new String[]{};
meth.invoke(null, (Object) params);
} finally {
System.setOut(console);
System.setIn(old);
}
}
}
在实际实施中,我还测量了执行代码所需的时间,并且能够设置阈值限制以进行测试。