FunTester Mock System.in 和检查 System.out

FunTester · 2020年04月28日 · 511 次阅读

做在单元测试的时候,会遇到测试数据依赖于用户输入的情况,类似于代码Scanner scanner = new Scanner(System.in);。下面提供一种方法,可以在测试过程中设置System.inSystem.out内容,很好地解决了模拟用户输入和检查输出的问题。

public MockInOut(String input) {
    orig = System.out;
    irig = System.in;

    os = new ByteArrayOutputStream();
    try {
        System.setOut(new PrintStream(os, false, charset.name()));
    } catch (UnsupportedEncodingException ex) {
        throw new RuntimeException(ex);
    }

    is = new ByteArrayInputStream(input.getBytes());
    System.setIn(is);
}

在这里设置了System.outSystem.in,因此我们可以在执行后完全获得输出,并且这次不需要手动输入,因为在的语句中Scanner scanner = new Scanner(System.in);,参数System.in是不会提示更改的,因此scanner.nextLine()将获得准备好的输入而无需等待。同样,输出将不会在控制台中打印,而是会累积到中ByteArrayOutputStream,随时可以访问。

如果想恢复System.inSystem.out我们该怎么办?

/**
 * 重置System.in、System.out
 */
public void close() {
    os = null;
    is = null;
    System.setOut(orig);
    System.setIn(irig);
}

基本上,它会保存原始对象和内容,in并且out在需要恢复时,只需清楚stream并将原来的其放回原处,然后一切将照常进行。

您可以在下面复制简单的示例代码以进行快速测试。

import java.io.*;
import java.util.*;

class HelloWorld {

    public static void main(String[] args) throws IOException {
        PrintStream orig = System.out;

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        System.setOut(new PrintStream(os, false, "UTF-8"));
        // 这里不会打印
        for (int i = 0; i < 2; i++) {
            System.out.println("FunTester" + i);
        }

        System.setOut(orig);
        // 打印重置前输出内容
        output("收集到的输出内容:" + os.toString("UTF-8"));

        InputStream is = System.in;
        System.setIn(new ByteArrayInputStream("FunTester\nFunTester\n".getBytes()));
        Scanner scanner = new Scanner(System.in);
        // 输出所有内容
        output(scanner.nextLine());
        output(scanner.nextLine());
        try {
            // 这里由于已经没有内容了,所以会报错
            System.out.println(scanner.nextLine());
        } catch (NoSuchElementException e) {
            e.printStackTrace();
        }

        System.setIn(is);
        scanner = new Scanner(System.in);
        // 这里会一直等待用户输入内容
        System.out.println("输入内容:" + scanner.nextLine());
    }

实际上,注入和替换是一种用于分离单元测试依赖关系的常用方法,这对于仅关注代码非常有用。有很多高级和复杂的方法可以执行此操作,但是在这里,我们只想解释一种简单的方法,即mock以便可以专注于代码。


  • 郑重声明:“FunTester” 首发,欢迎关注交流,禁止第三方转载。

技术类文章精选

无代码文章精选

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册