我必须在一个类中测试一个方法,该类使用scanner类获取输入。
package com.math.calculator;
import java.util.Scanner;
public class InputOutput {
public String getInput() {
Scanner sc = new Scanner(System.in);
return sc.nextLine();
}
}
我想用junit来测试它,但不知道怎么做。
我试着使用下面的代码,但它不起作用。
package com.math.calculator;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class InputOutputTest {
@Test
public void shouldTakeUserInput() {
InputOutput inputOutput= new InputOutput();
assertEquals("add 5", inputOutput.getInput());
}
}
我也想用mockito(使用mock。。。什么时候。。。然后返回)但不知道怎么做。
4条答案
按热度按时间zpgglvta1#
你可以改变主意
System.in
流使用System.setIn()
方法。试试这个,
您刚刚修改了
System.in
现场。System.in
基本上是一个InputStream
上面写着console
(因此在控制台中输入)。但您只是修改了它,让系统从提供的inputstream
相反。所以它不再从控制台读取,而是从提供的输入流读取。h79rfbju2#
您可以使用
TextFromStandardInputStream
系统规则库的规则。3vpjnl9f3#
首先,我假设您的测试的目标是验证用户输入是从扫描器获得的,并且返回的值是扫描器中输入的值。
mocking不起作用的原因是每次在
getInput()
方法。因此,无论你做什么,你的mockito示例永远不会被调用。因此,使该类可测试的正确方法是标识该类的所有外部依赖项(在本例中为java.util.Scanner
并通过构造函数将它们注入类中。这样,您就可以在测试期间注入模拟扫描仪示例。这是实现依赖注入的基本步骤,而依赖注入又会导致良好的tdd。举个例子可以帮助您:现在你的测试方法是:
还要注意的是,由于在上面的类中我是使用构造函数注入的,所以我已经声明了scanner示例final。因为我在这个类中没有更多的可变状态,所以这个类是线程安全的。
基于构造函数的依赖注入的概念非常酷,值得在互联网上阅读。它有助于开发良好的线程安全可测试代码。
b1payxdu4#
除了switching system.in之外,正如codebender也提到的,考虑重构也是如此
getInput()
变成了一个彻底的getInput(Scanner)
方法,您可以通过创建自己的Scanner("your\ntest\ninput\n")
. 有很多其他的方法来注入你的扫描仪依赖性,比如让你覆盖一个字段进行测试,但是仅仅让一个方法重载是非常容易的,技术上给你更多的灵活性(比如让你添加一个特性来读取文件的输入)。总的来说,要记住设计要容易测试,而且测试高风险的部件要比测试低风险的部件重。这意味着重构是一个很好的工具,而测试
getInput(Scanner)
可能比测试更重要getInput()
尤其是你不仅仅是打电话nextLine()
.我强烈建议不要创建模拟scanner:模拟一个不属于自己的类型不仅是一种不好的做法,而且scanner代表了一个非常大的相关方法api,调用顺序非常重要。在mockito中复制它意味着要么在mockito中创建一个大的假scanner实现,要么模拟一个只测试所做调用的最小实现(如果实现发生了更改,即使您的更改提供了正确的结果,也会中断)。使用真正的扫描器并保存mockito实践,以用于外部服务调用或模拟您定义的小型但未编写的api的情况。