Я пытаюсь разработать сценарий автоматической оценки назначения с использованием JUnit в Java. Я имитирую пользовательский ввод, передавая входные данные тестового примера (считанные из файла в classpath), меняя System.in на ByteArrayInputStream, содержащий строковые данные в байтах. Я хочу иметь возможность запускать несколько тестовых случаев, чтобы проверить все случаи, а затем использовать построенный Gradle отчет, чтобы отметить отправку назначения.
В настоящее время мне удалось смоделировать пользовательский ввод, чтобы отразить ввод данных, предоставленных тестовыми примерами, используя эту ссылку: JUnit: Как смоделировать тестирование System.in? . Я также изменяю System.out на PrintStream для захвата напечатанных операторов из назначения. Мой основной метод порождает новый поток, внутри которого выполняются коды назначения, как показано ниже.
Модульные тесты успешно выполняются, когда я тестирую каждый аннотированный @Test случай отдельно. Однако, когда я запускаю все тесты, содержащиеся в одном классе Test, JUnit успешно работает в первом случае с аннотацией @Test, но терпит неудачу с возможными, что здесь несколько неожиданно. Надеемся, что приведенные ниже коды помогут прояснить ситуацию.
Мой метод Main :
public static void main(String ... args) {
Assignment assignment = new Assignment();
new Thread(assignment).start();
}
В моем тестовом классе есть несколько аннотированных методов @before и @after:
@Before
public void setup() {
systemIn = System.in; // global variable
systemOut = System.out; // global variable
output = new ByteArrayOutputStream(); // global variable
System.setOut(new PrintStream(output));
assignment = new Assignment();
}
@After
public void conclude() {
System.setIn(systemIn);
System.setOut(systemOut);
}
Я читаю соответствующий файл для каждого ввода и вывода тестового примера, а в приведенной ниже функции я устанавливаю ввод тестового набора.
private void setInput(String data) {
ByteArrayInputStream input = new ByteArrayInputStream(data.getBytes());
System.setIn(input);
}
Я выполняю каждый тестовый пример следующим образом:
@org.junit.Test // 2,3,4 ....for other cases
public void runTestCase1() {
testCases(1);
}
Класс IO , который использует присвоение, выглядит следующим образом:
public static String readLine() { // w/o try/catch blocks
String read = reader.readLine(); // reader -> bufferedReader(new InputStream(System.in))
return read.trim();
}
Также обратите внимание, что я использую Thread.sleep(50)
перед вызовом основного метода, чтобы входной тестовый пример был успешно прочитан и загружен в System.in во время выполнения Назначения.
При запуске всех тестов вместе, первый тест дает правильный результат, то есть совпадают ожидаемый и фактический выходы. Однако для второго случая и далее IO.readline()
генерирует исключение нулевого указателя , и, следовательно, присвоение не приводит к выводу. После расследования я обнаружил, что во втором случае System.in
больше не указывает на ByteArrayInputStream, а скорее (старый?) BufferedInputStream. Я не понимаю, почему это может происходить (возможно, из-за появления нового потока?) И как мне преодолеть эту проблему?