[英]How to mock console user input in mockito test cases
I want to mock the console input in test cases under junit/mockito can any one please help me. 我想在junit / mockito下的测试用例中模拟控制台输入,任何人都可以帮助我。 My source code:
我的源代码:
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");
}
}
The other answer is correct, but in the end, you are rather looking at a "design" problem here; 另一个答案是正确的,但最后,你更倾向于看一个“设计”问题; and fixing that will make your code much easier to test.
并修复将使您的代码更容易测试。
Your problem originates from the fact that you want to test the System console. 您的问题源于您要测试系统控制台的事实。 But that is ... actually a bad idea.
但那......实际上是一个坏主意。
You see, in the end, you will want to make sure that one part of your program has a "source" where it can "read" information from. 你会看到,最后,你需要确保你的程序的一部分有一个“源”,它可以从中“读取”信息。 You "fixated" that source to be the console.
您“固定”了该源作为控制台。 That seems logical but is actually wrong .
这似乎合乎逻辑但实际上是错误的 。
You want to abstract from specific implementations; 您希望从特定实现中抽象出来; instead you want to use interfaces or "base classes" where possible.
相反,你想尽可能使用接口或“基类”。 For example: java.io.Reader .
例如: java.io.Reader 。 If you do that, you could write your code as:
如果这样做,您可以将代码编写为:
public class ConsoleReader {
private final Reader source;
public ConsoleReader() { this ( System.console.reader() ); }
ConsoleReader(Reader source) { this.source = source; }
The above allows you to: 以上允许您:
And now you don't have to mock a method in Console; 现在你不必在Console中模拟一个方法; but you mock Reader;
但你嘲笑读者; and are free to mock any method of that class!
并且可以自由地模仿该类的任何方法!
Long story short: you came up with an inflexible design, that is also hard to test. 长话短说:你想出了一个不灵活的设计,也很难测试。 The answer is not to circumvent that problem using mocking framework tricks;
答案是不要使用模拟框架技巧来规避这个问题; but to improve the design;
但要改进设计; so it can be tested easier!
所以它可以更容易测试!
Yes, the Console
class is final
, so Mockito can not directly mock it by creating a sub-class. 是的,
Console
类是final
,所以Mockito不能通过创建子类来直接模拟它。 To work around this, you have to isolate the interaction in another method or a wrapper class. 要解决此问题,您必须在另一个方法或包装类中隔离交互。 Then you mock this method or the wrapper.
然后你模拟这个方法或包装器。
The concrete problem in your code: You can not mock a static method. 代码中的具体问题:您无法模拟静态方法。 Just remove the
static
modifier from readFromConsole()
. 只需从
readFromConsole()
删除static
修饰符readFromConsole()
。
Some observations on your code example: 对您的代码示例的一些观察:
System.console()
it returns "The system console, if any, otherwise null.", so your production code should handle the null
case. System.console()
的Javadoc,它返回“系统控制台,如果有的话,否则为null。”,所以你的生产代码应该处理null
情况。 Console
you could read from System.in
which can be switched by eg System.setIn(new ByteArrayInputStream("This is not console".getBytes(StandardCharsets.UTF_8)));
Console
你可以从System.in
读取,可以通过例如System.setIn(new ByteArrayInputStream("This is not console".getBytes(StandardCharsets.UTF_8)));
切换System.setIn(new ByteArrayInputStream("This is not console".getBytes(StandardCharsets.UTF_8)));
cs
as an instance of ConsoleSrc
with a String
will always fail cs
作为ConsoleSrc
的实例与String
将始终失败
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.