我想在junit / mockito下的测试用例中模拟控制台输入,任何人都可以帮助我。我的源代码:
import java.io.Console;
public class ConsoleSrc {
public static String readFromConsole() {
String str = null;
try {
Console con = System.console();
System.out.println("The console object is: " + con);
str = con.readLine();
System.out.println("String is : " + str);
} catch (Exception ex) {
ex.printStackTrace();
}
return str;
}
public static void main(String[] args) {
ConsoleSrc cs = new ConsoleSrc();
String str = cs.readFromConsole();
System.out.println("String is : " + str);
}
}
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ConsoleTest {
@Test
public void ConsoleSrcTestSuccess() {
ConsoleSrc cs = mock(ConsoleSrc.class);
when(cs.readFromConsole()).thenReturn("##This is not console##");
assertEquals(cs, "This is not console");
}
}
答案 0 :(得分:2)
另一个答案是正确的,但最后,你更倾向于看一个“设计”问题;并修复将使您的代码更多更容易测试。
您的问题源于您要测试系统控制台的事实。但那......实际上是一个糟糕的想法。
你会看到,最后,你需要确保程序的一部分有一个“源”,它可以从中“读取”信息。您“固定”了该源作为控制台。这似乎合乎逻辑,但实际上错误。
您希望从特定实现抽象;相反,你想尽可能使用接口或“基类”。例如:java.io.Reader。如果这样做,您可以将代码编写为:
public class ConsoleReader {
private final Reader source;
public ConsoleReader() { this ( System.console.reader() ); }
ConsoleReader(Reader source) { this.source = source; }
以上允许您:
现在你不必在Console中模拟一个方法;但你嘲笑读者;并可以自由地模仿该类的任何方法!
长话短说:你想出了一个不灵活的设计,也很难测试。答案是不要使用模拟框架技巧来规避这个问题;但要改进设计;所以它可以更容易测试!
答案 1 :(得分:1)
是的,Console
类是final
,因此Mockito无法通过创建子类来直接模拟它。要解决此问题,您必须在另一个方法或包装类中隔离交互。然后你模拟这个方法或包装器。
代码中的具体问题:您无法模拟静态方法。只需从static
删除readFromConsole()
修饰符。
对您的代码示例的一些观察:
System.console()
的Javadoc,它返回“系统控制台,如果有的话,否则为null。”,所以你的生产代码应该处理null
的情况。Console
,您可以从System.in
读取,可以通过例如System.setIn(new ByteArrayInputStream("This is not console".getBytes(StandardCharsets.UTF_8)));
进行切换。 cs
ConsoleSrc
作为String
的实例与<select id="selector" ng-select="selector" data-ng-init=init() >
...
</select>
进行比较将始终失败