Перенаправленный System.in ByteArrayInputStream считывается на один тест JUnit слишком поздно - PullRequest
1 голос
/ 06 мая 2020

Я сейчас пишу тесты Junit для автоматического тестирования студенческих задач. Topi c - это консольный ввод в java. У меня есть несколько тестов, в которых необходимо смоделировать ввод данных пользователем и проверить правильность поведения проверенных методов (метод работает нормально).

Моя проблема на данный момент: ByteArrayInputStream, установленный как System.in, не будет выпущен, когда потребуется, но через один тест (см. Pi c ниже).

Я попытался сбросить поток , сделайте его stati c, сделайте его нестандартным c, установите стандартные System.in до и после, попробовал метод чтения, переключил java -версии (с SE13 на 1.8). Все попытки в разное время, c.

enter image description here

Пояснение к выводу на картинке:

Это из нашего автоматизированного JUnit -Фреймворк. Это два теста, основанные на проверяемом методе, который требует ввода данных пользователем. Знак "?" в начале строки указывают, что тестируемый метод активен и ожидает. Первые два слова после строки STARTING TEST - это то, что должно быть введено.

Тестовый код 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);
}

Протестированные 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;
    }
}

Помощь очень ценится . Невозможно изменить используемую библиотеку Junit или добавить другие внешние библиотеки atm.

1 Ответ

0 голосов
/ 06 мая 2020

Я написал для вас следующий фрагмент:

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

Как видите, BufferedReader правильно готов "test" из входящего потока. Я использовал аспект AutoClosable для ByteArrayInputStream, чтобы закрыть его после блока кода.

Поскольку это не решает вашу проблему, я не уверен, не возникает ли проблема в окружающей среде. В частности, единственное объяснение, которое я могу придумать для перехода значений от Testcase 1 к Testcase 2, заключается в том, что объект не создается повторно, а каким-то образом повторно используется. Так как этот код отсутствует, этого нельзя сказать наверняка.

...