繁体   English   中英

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

[英]How to mock console user input in mockito test cases

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

ConsoleSrc.java

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);
  }
}

测试代码ConsoleTest.java

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");
  }
}

另一个答案是正确的,但最后,你更倾向于看一个“设计”问题; 并修复将使您的代码容易测试。

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

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

您希望从特定实现中抽象出来; 相反,你想尽可能使用接口或“基类”。 例如: java.io.Reader 如果这样做,您可以将代码编写为:

public class ConsoleReader {
  private final Reader source;

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

以上允许您:

  • 使用默认的no-arg构造函数创建ConsoleReader对象; 然后它将从System.console读取
  • 但是,您也可以使用其他构造函数,并为您正在测试的类提供任何类型的读者。 例如:由Mockito创建的模拟读者。

现在你不必在Console中模拟一个方法; 但你嘲笑读者; 并且可以自由地模仿该类的任何方法!

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

是的, Console类是final ,所以Mockito不能通过创建子类来直接模拟它。 要解决此问题,您必须在另一个方法或包装类中隔离交互。 然后你模拟这个方法或包装器。

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

对您的代码示例的一些观察:

  • 根据System.console()的Javadoc,它返回“系统控制台,如果有的话,否则为null。”,所以你的生产代码应该处理null情况。
  • 而不是使用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)));
  • assertEquals调用没有意义,原因有两个:
    • cs作为ConsoleSrc的实例与String将始终失败
    • 对模拟返回值的断言不会测试代码,而是测试模拟框架

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM