Тестирование асинхронного кода с помощью JUnit - PullRequest
8 голосов
/ 12 декабря 2011

Я хочу протестировать некоторый код, который использует сетевую передачу. Код делает запрос и предоставляет обратный вызов - когда запрос завершается, обратный вызов запускается. Я хотел бы смоделировать передачу по сети и использовать Thread.sleep для имитации некоторой задержки ... но, конечно, это заставит весь тест приостановиться.

До сих пор я создавал новые потоки и использовал CountDownLatch es на протяжении всего теста, чтобы остановить завершение теста до запуска обратного вызова. Мой фиктивный сетевой объект создает новый поток, спит в этом потоке, а затем запускает обратный вызов. Это на самом деле работает довольно хорошо, но проблема в том, что о любых ошибках утверждения в обратном вызове не сообщается исходному потоку junit - вместо этого я получаю текст исключения в консоли, где его намного сложнее понять и использовать.

Я надеюсь, что есть либо:

  1. Способ передачи assertEquals вывода из порожденных потоков в главный выходной коллектор JUnit или
  2. Совершенно другой и лучший способ тестирования многопоточного кода в JUnit, или
  3. Какой-то способ симулировать асинхронный код в одном потоке

Спасибо за любые идеи!

Ответы [ 2 ]

4 голосов
/ 12 декабря 2011

Когда мне пришлось реализовать асинхронный механизм, аналогичный вашему, я создал абстрактный класс AsyncTestCase, который содержит тестовую ошибку и предоставляет специальный метод waitForCallback(). Когда асинхронная задача находит ошибку в ожидаемых результатах, она помещает ошибку в эту переменную. Сеттер вызывает notify() для объекта, который используется waitForCallback(). Таким образом, когда приходит обратный вызов, он немедленно вызывает пробуждение теста. Затем я могу вызвать все утверждения, включая то, которое было сохранено асинхронной задачей.

И не забудьте поставить тайм-аут на тесты, чтобы они не спали вечно:

@Test(timeout=10000)
public void mytest() {
    callAsyncTask();
    waitForAsyncTask();       // from base class
    assertAsyncTaskResult();  // from base class
}
1 голос
/ 24 июля 2015

То, что вы описываете, это ConcurrentUnit .Вот пример:

  final Waiter waiter = new Waiter();

  new Thread(() -> {
    doSomeWork();
    waiter.assertTrue(true);
    waiter.resume();
  }).start();

  // Wait for resume() to be called
  waiter.await(1000);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...