JUnit завершает дочерние потоки - PullRequest
17 голосов
/ 14 мая 2010

Когда я тестирую выполнение метода, который создает дочерний поток, тест JUnit заканчивается перед дочерним потоком и убивает его.

Как заставить JUnit дождаться завершения выполнения дочернего потока?

Спасибо

Ответы [ 6 ]

8 голосов
/ 15 мая 2010

После прочтения вопроса и некоторых комментариев кажется, что вам нужна методика для модульного тестирования асинхронных операций . doSomething () возвращается немедленно, но вы хотите, чтобы тестовый код ожидал его завершения, а затем провел несколько проверок.

Проблема в том, что тест не знает о потоках, порождаемых вызовом, поэтому, очевидно, у него нет средств для их ожидания. Можно придумать много сложных (и, возможно, ошибочных) способов решения этой проблемы, но, на мой взгляд, здесь есть проблема дизайна. Модульный тест должен имитировать клиента какого-либо API, и он не должен предполагать ничего о реализации; Следует только тестировать функциональность, как это отражено в API и его документации. Поэтому я бы избегал попыток обнаруживать и отслеживать потоки, созданные асинхронным вызовом. Вместо этого я бы улучшил API тестируемого класса, если это необходимо. Класс, к которому относится асинхронный вызов, должен обеспечивать некоторый механизм для обнаружения завершения. Я могу придумать 3 способа, но, вероятно, есть еще:

1) Разрешить регистрацию слушателя, который получает уведомление после завершения операции

2) Предоставление синхронной версии операции. Реализация может вызвать асинхронную версию, а затем заблокировать до завершения. Если класс не должен предоставлять такой метод, его видимость может быть уменьшена до защищенного пакета, чтобы тест мог получить к нему доступ.

3) Использование шаблона ожидания-оповещения для какого-либо видимого объекта.

Если класс не предоставляет такого механизма, то он не является действительно тестируемым, и, что еще хуже, его, вероятно, также нельзя использовать повторно.

2 голосов
/ 14 мая 2010

Попробуйте использовать thread.join () в созданном потоке. Это будет ждать, когда эта нить умрет.

Редактировать: чтобы избежать этого, попробуйте Thread.getThreadGroup().setDaemon(true); в тесте или, возможно, в методе setUp(). Я не проверял это все же.

Группа потоков демона автоматически уничтожается, когда его последний поток останавливается или его последняя группа потоков уничтожается.

Интересно, JUnit вызывает System.exit() или что-то еще, как только тест завершится, однако.

1 голос
/ 21 июня 2011

Базовый метод, который обрисовал в общих чертах @Eyal, предназначен для ConcurrentUnit Общее использование:

  1. порождает некоторые темы
  2. Попросить основной поток подождать или поспать
  3. Выполнение утверждений из рабочих потоков (которые через ConcurrentUnit возвращаются в основной поток)
  4. Возобновить основной поток из одного из рабочих потоков после завершения всех утверждений

См. Страницу ConcurrentUnit для получения дополнительной информации.

0 голосов
/ 08 марта 2019

В java попробуйте использовать CountDownLatch, чтобы заставить основной поток ждать завершения дочернего потока.

    @Test
    public void myTest() {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        new Thread(new Runnable() {
            @Override
            public void run() {
                //write your logic here
                countDownLatch.countDown();
            }
        }).start();
        //wait until the child thread completed.
        countDownLatch.await();
    }
0 голосов
/ 06 декабря 2013
        while (s.isRunning()) {
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

Вы можете попытаться заблокировать поток JUnit и дождаться его завершения. Thread.sleep() необходим, чтобы ваш поток не нагружал процессор. В этом примере s будет вашим потоком, вам понадобится метод isRunning(), чтобы вы могли проверять, работает ли поток каждые SLEEP_TIME миллисекунды. Я знаю, что это не самое лучшее решение, но если у вас есть только 2 потока, и вы не хотите, чтобы JUnit убивал ваш поток, это работает. Цикл while с заставляет этот поток JUnit оставаться в живых и ждать завершения другого потока.

0 голосов
/ 14 мая 2010

Возможно сгруппировать ваши темы с помощью ExecutorService , затем использовать shutdown и awaitTermination method?

Условие - использовать Runnable или Future, а не сами Threads.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...