Java 如何在mockito测试用例中模拟控制台用户输入

Java 如何在mockito测试用例中模拟控制台用户输入,java,junit,mockito,Java,Junit,Mockito,我想在junit/mockito下模拟测试用例中的控制台输入,请任何人帮助我。我的源代码: ConsoleSrc.java 测试代码ConsoleTest.java 是的,Console类是final,因此Mockito不能通过创建子类直接模拟它。为了解决这个问题,您必须在另一个方法或包装器类中隔离交互。然后模拟此方法或包装器 代码中的具体问题是:不能模拟静态方法。只需从readFromConsole()中删除static修饰符 对代码示例的一些观察: 根据System.console()的J

我想在junit/mockito下模拟测试用例中的控制台输入,请任何人帮助我。我的源代码:

ConsoleSrc.java 测试代码ConsoleTest.java
是的,
Console
类是
final
,因此Mockito不能通过创建子类直接模拟它。为了解决这个问题,您必须在另一个方法或包装器类中隔离交互。然后模拟此方法或包装器

代码中的具体问题是:不能模拟静态方法。只需从
readFromConsole()
中删除
static
修饰符

对代码示例的一些观察:

  • 根据
    System.console()
    的Javadoc,它返回“系统控制台,如果有的话,否则为null”,因此您的生产代码应该处理
    null
    情况
  • 您可以从
    System.in
    读取,而不是使用
    Console
    ,例如,可以通过
    System.setIn(新的ByteArrayInputStream(“这不是Console.getBytes(StandardCharsets.UTF_8)))进行切换
  • assertEquals调用没有意义,原因有二:
    • cs
      作为
      ConsoleSrc
      的实例与
      字符串进行比较总是失败的
    • 对模拟返回值的断言不会测试代码,而是测试模拟框架

另一个答案是正确的,但最终,您看到的是一个“设计”问题;修复它将使您的代码更易于测试

您的问题源于您想要测试系统控制台这一事实。但那是。。。实际上是个坏主意

你看,最后,你要确保你的程序的一部分有一个“源”,它可以从中“读取”信息。您“固定”该源作为控制台。这似乎合乎逻辑,但实际上是错误的

您希望从特定实现中提取;相反,您希望尽可能使用接口或“基类”。例如:。如果这样做,您可以将代码编写为:

public class ConsoleReader {
  private final Reader source;

  public ConsoleReader() { this ( System.console.reader() ); }
  ConsoleReader(Reader source) { this.source = source; }
以上内容允许您:

  • 使用默认的无参数构造函数创建ConsoleReader对象;然后它将从System.console读取
  • 但是,您也可以使用other构造函数,并为您的测试类提供任何类型的读取器。例如:Mockito创建的模拟阅读器
现在您不必在控制台中模拟方法;但你嘲笑读者;并且可以自由地模仿该类的任何方法


长话短说:您提出了一个不灵活的设计,这也很难测试。答案不是使用模拟框架技巧来回避这个问题;但要改进设计;因此,它可以更容易地测试

你有什么问题?这个断言毫无意义。您正在使用字符串对模拟的ConsoleRC实例执行等于检查。您可能希望将其更改为
assertEquals(cs.readFromConsole(),“这不是控制台”)
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");
  }
}
public class ConsoleReader {
  private final Reader source;

  public ConsoleReader() { this ( System.console.reader() ); }
  ConsoleReader(Reader source) { this.source = source; }