private Deque<String> inputLinesDeque;
void setInputLines(List<String> inputLines) {
inputLinesDeque = new ArrayDeque<String>(inputLines);
}
private String getInputLine() throws Exception {
if (inputLinesDeque == null) {
// ... i.e. normal case, during app run: this is then a blocking method
return br.readLine();
}
String nextLine = null;
try {
nextLine = inputLinesDeque.pop();
} catch (NoSuchElementException e) {
// when the Deque runs dry the line returned is a "poison pill",
// signalling to the caller method that the input is finished
return "q";
}
return nextLine;
}
9条答案
按热度按时间bqjvbblv1#
从技术上讲,可以切换
System.in
,但一般来说,不直接在代码中调用它会更健壮,而是添加一个间接层,以便从应用程序中的一个点控制输入源。具体如何做到这一点是一个实现细节-依赖注入的建议是好的,但不一定需要引入第三方框架;例如,您可以从调用代码传递一个I/O上下文。如何切换
System.in
:wlwcrazw2#
基于@McDowell的答案和another answer that shows how to test System.out,我想分享我的解决方案,为程序给予输入并测试其输出。
作为参考,我使用JUnit 4.12。
假设我们有这样一个程序,它只是将输入复制到输出:
要测试它,我们可以使用以下类:
我不会解释太多,因为我相信代码是可读的,我引用了我的来源。
当JUnit运行
testCase1()
时,它将按照helper方法出现的顺序调用它们:setUpOutput()
,因为@Before
注解provideInput(String data)
,从testCase1()
调用getOutput()
,从testCase1()
调用restoreSystemInputOutput()
,因为@After
注解我没有测试
System.err
,因为我不需要它,但是它应该很容易实现,类似于测试System.out
。zpgglvta3#
有几种方法可以实现这一点。最完整的方法是在运行被测类的同时传入一个InputStream,它是一个假的InputStream,将模拟数据传递给你的类。如果你需要在代码中经常这样做,你可以考虑依赖注入框架(比如Google Guice),但最简单的方法是:
在测试中,你会调用接受输入流的构造函数,你甚至可以将构造函数包私有化,并将测试放在同一个包中,这样其他代码通常就不会考虑使用它。
5q4ezhmt4#
尝试重构你的代码以使用dependency injection。不要让你的a方法直接使用
System.in
,而是让该方法接受一个InputStream
作为参数。然后在junit测试中,你将能够通过一个测试InputStream
实现来代替System.in
。r7xajy2e5#
您可以使用System Rules库的
TextFromStandardInputStream
规则为命令行界面编写一个clear测试。充分披露:我是那个图书馆的作者。
uqxowvwt6#
您可以创建一个自定义的
InputStream
并将其附加到System
类然后将其与您的
Scanner
一起使用System.in = new FakeInputStream();
之前:
之后:
虽然我认为你应该更好地测试你的类应该如何处理从输入流中读取的数据,而不是测试它如何从那里读取数据。
f0brbegy7#
BufferedReader.readLine()
的问题在于它是一个等待用户输入的阻塞方法。在我看来,你并不特别想模拟它(即你希望测试更快)。但在测试上下文中,它在测试过程中不断地以高速返回null
,这是令人讨厌的。对于一个纯粹主义者来说,你可以把下面的
getInputLine
设置为package-private,然后嘲笑它:轻松的......你必须确保你有办法停止(通常)用户与应用程序的交互循环。你还必须科普这样一个事实,即你的“输入行”总是相同的,直到你以某种方式改变了你的mock的
doReturn
:几乎不是典型的用户输入。对于一个非纯粹主义者来说,如果他希望让生活变得简单(并生成可读的测试),你可以把下面的所有东西放在你的应用代码中:
......在测试中,您可能会这样做:
在触发这个“ConsoleHandler”类中需要输入行的方法之前。
rdlzhqv98#
可能是这样的(未测试):
更多部件:
w41d8nur9#
@斯特凡·伯克纳,谢谢!
1.修改Pom.xml
1.添加功能代码
1.添加测试代码