简体   繁体   English

重定向 System.in ByteArrayInputStream 被读取一个 JUnit 测试为时已晚

[英]Redirected System.in ByteArrayInputStream is read one JUnit test too late

I am Currently writing Junit tests for automated testing of student tasks.我目前正在编写 Junit 测试,用于自动测试学生任务。 The topic is console input in java.主题是 java 中的控制台输入。 I have multiple tests that need to take simulated user input and check for correct behaviour of tested methods (method is working fine).我有多个测试需要模拟用户输入并检查测试方法的正确行为(方法工作正常)。

My problem at the moment: the ByteArrayInputStream set as System.in won't release when needed but one test later (see pic below).我目前的问题:设置为System.in的 ByteArrayInputStream 不会在需要时发布,但稍后会进行一次测试(见下图)。

I tried to reset the stream, make it static, make it non-static, have standard System.in set before and after, tried read method, switched java-versions (from SE13 to 1.8).我尝试重置 stream,使其成为 static,使其成为非静态,前后设置标准System.in ,尝试读取方法,切换 java 版本(从 SE13 到 1.8)。 All attempts at different times, ofc.不同时间的所有尝试,ofc。

在此处输入图像描述

Explanation of output in the picture:图中output说明:

It's from our automated JUnit-Framework.它来自我们的自动化 JUnit 框架。 Those are two tests reliant on the tested method that takes a user input.这两个测试依赖于接受用户输入的测试方法。 The "?"这 ”?” at the start of a line indicate the tested method is active and waiting.在一行的开头表示测试的方法处于活动状态并正在等待。 First two words after the STARTING TEST line are what is supposed to get injected. STARTING TEST 行之后的前两个单词应该被注入。

JUnit test code: JUnit 测试代码:

final  static InputStream STDIN = System.in;
static ByteArrayInputStream bais;
final static String[] INJECTIONS = { "abc", "def", "ghi", "jkl", "mmmm", "klopp", "urgl", "gurle", "ding", "dong" };

private static void inject(String injection, Object o, MethodSignature ms) {
    System.out.println(injection);

    try {
        ByteArrayInputStream bais = new ByteArrayInputStream(injection.getBytes("UTF-8"));

        System.setIn(bais);
        System.out.println("Injection Bytes: "+injection.getBytes().length);
        System.out.println("Available for injection: " + System.in.available());

        ms.getMethod().invoke(o);

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        System.setIn(STDIN);
    }
}

private static String getStringInject(String injection, Object o, MethodSignature ms) {
    String out = null;
    System.out.println(injection);
    try {

        ByteArrayInputStream bais = new ByteArrayInputStream(injection.getBytes("UTF-8"));

        System.setIn(bais);
        System.out.println("Injection Bytes: "+injection.getBytes().length);
        System.out.println("Available for injection: " + System.in.available());
        System.in.reset();
        out = (String) ms.getMethod().invoke(o);

    } catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        System.setIn(STDIN);
    }
    return out;
}

@Test
public void checkReadFromConsoleCorrectReturnTest() {

    Object o = createObject(csMain.getC());
    if (o == null) {
        addFail(csMain.getObjectFail());
        return;
    }
    String injection = INJECTIONS[ThreadLocalRandom.current().nextInt(0, INJECTIONS.length)];

    String output = getStringInject(injection + System.lineSeparator() + "END" + System.lineSeparator(), o,
            msReadFromConsole);

    if (output == null || output.isEmpty()) {
        addFail(msReadFromConsole.getMethodNoReturnString());
        return;
    }

}

@Test
public void checkReadCorrectEndingTriggerTest() {

    Object o = createObject(csMain.getC());
    if (o == null) {
        addFail(csMain.getObjectFail());
        return;
    }
    String injection = INJECTIONS[ThreadLocalRandom.current().nextInt(0, INJECTIONS.length)]
            + System.lineSeparator() + "END" + System.lineSeparator();


    inject(injection, o, msRead);
}

Tested java methods:测试 java 方法:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class ConsoleReader implements IConsoleReader {

    ArrayList<String> reads;
    BufferedReader br;

    public ConsoleReader() {
        reads = new ArrayList<String>();
        br = new BufferedReader(new InputStreamReader(System.in));
    }

    public void read() {
        String input = readFromConsole();
        while (true) {
            if (input == null || input.isEmpty()) {
                System.out.println("ERROR: null");
                return;
            }
            input = input.trim().toUpperCase();

            if (input.equals("END")) {
                System.out.println("Done.");
                return;
            }

            reads.add(input);
            input = readFromConsole();
        }
    }

    public String readFromConsole() {
        System.out.print("? ");
        String out = null;
        try {
            out = br.readLine();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        System.out.println(out);
        return out;
    }
}

Help is much appreciated.非常感谢您的帮助。 Can't change the Junit library used or add other external libraries atm.无法更改使用的 Junit 库或添加其他外部库 atm。

I wrote the following snippet for you to run:我编写了以下代码段供您运行:

@Test
public void test_byteArrayInputStream() {
    InputStream STDIN = System.in;
    String message = "test" + System.lineSeparator();
    try (ByteArrayInputStream in = new ByteArrayInputStream(message.getBytes("UTF-8"))) {
        System.setIn(in);

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        assertEquals("test", br.readLine()); // this succeeds
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        System.setIn(STDIN);
    }
}

As you can see, the BufferedReader correctly ready "test" from the in stream.如您所见, BufferedReader从 stream 中正确准备好"test" I used the AutoClosable aspect of ByteArrayInputStream to close it after the code block.我使用ByteArrayInputStreamAutoClosable方面在代码块之后关闭它。

Since this does not solve your problem, I am uncertain whether the problem does not originate in the surrounding framework.由于这不能解决您的问题,因此我不确定问题是否源于周围的框架。 More specifically, the only explanation I can think of for the leap over of values from Testcase 1 to Testcase 2 is, that the object is not reinstantiated, but reused somehow.更具体地说,对于从测试用例 1 到测试用例 2 的值的跨越,我能想到的唯一解释是,object 没有重新实例化,而是以某种方式重用。 Since this code is missing, it cannot be said for sure.由于缺少此代码,因此无法确定。

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

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