Как написать модульный тест для «InterruptedException» - PullRequest
11 голосов
/ 14 сентября 2010

В попытках 100% покрытия кода я столкнулся с ситуацией, когда мне нужно выполнить модульный тест блока кода, который перехватывает InterruptedException.Как правильно это проверить?(Синтаксис JUnit 4, пожалуйста)

private final LinkedBlockingQueue<ExampleMessage> m_Queue;  

public void addMessage(ExampleMessage hm) {  
    if( hm!=null){
        try {
            m_Queue.put(hm);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Ответы [ 5 ]

16 голосов
/ 14 сентября 2010

Прямо перед вызовом addMessage(), позвоните Thread.currentThread().interrupt(). Это установит флаг состояния «прерывание» в потоке.

Если статус прерывания установлен, когда на LinkedBlockingQueue сделан вызов на put(), InterruptedException будет повышен, даже если для put ожидание не требуется (блокировка не оспаривается ).

Кстати, некоторые усилия по достижению 100% покрытия являются контрпродуктивными и могут фактически ухудшить качество кода.

13 голосов
/ 14 сентября 2010

Используйте библиотеку-насмешку, например Easymock, и вставьте макет LinkedBlockingQueue

т.е.

@Test(expected=InterruptedException.class)
public void testInterruptedException() {
    LinkedBlockingQueue queue = EasyMock.createMock(LinkedBlockingQueue.class);
    ExampleMessage message = new ExampleMessage();
    queue.put(message);
    EasyMock.expectLastCall.andThrow(new InterruptedException()); 
    replay(queue);
    someObject.setQueue(queue);
    someObject.addMessage(msg);
}
1 голос
/ 21 мая 2015

Другой вариант - делегировать работу с InterruptedException на Guava Uninterruptibles, поэтому вам не нужно писать и тестировать свой собственный код для него:

import static com.google.common.util.concurrent.Uninterruptibles.putUninterruptibly;

private final LinkedBlockingQueue<ExampleMessage> queue;  

public void addMessage(ExampleMessage message) {  
    putUninterruptibly(queue, message);
}
0 голосов
/ 07 сентября 2018

Как указано выше, просто используйте Thread.currentThread().interrupt(), если вы поймали InterruptedException и не собираетесь его отбрасывать.

Что касается модульного тестирования.Протестируйте так: Assertions.assertThat(Thread.interrupted()).isTrue();.Он одновременно проверяет, что поток был прерван, и сбрасывает флаг прерывания, чтобы не нарушать другие тесты, покрытие кода или что-либо ниже.

0 голосов
/ 15 июня 2018

Одним из правильных способов может быть настройка / внедрение ThreadFactory для executorservice, и из фабрики потоков вы получите дескриптор созданного потока, а затем вы можете запланировать некоторую задачу для прерывания интересующего потока.

Демонстрационная часть кода для переписанного метода "newThread" в ThreadFactory:

ThreadFactory customThreadfactory new ThreadFactory() {

            public Thread newThread(Runnable runnable) {
                final Thread thread = new Thread(runnable);
                if (namePrefix != null) {
                    thread.setName(namePrefix + "-" + count.getAndIncrement());
                }
                if (daemon != null) {
                    thread.setDaemon(daemon);
                }
                if (priority != null) {
                    thread.setPriority(priority);
                }

                scheduledExecutorService.schedule(new Callable<String>() {
                    public String call() throws Exception {
                        System.out.println("Executed!");
                        thread.interrupt();
                        return "Called!";

                    }
                },
                5,
                TimeUnit.SECONDS);

                return thread;
            }
        }

Затем вы можете использовать ниже для создания вашего экземпляра executorservice:

ExecutorService executorService = Executors.newFixedThreadPool(3,
        customThreadfactory);

Затем через 5 секунд прерываниесигнал будет отправлен потокам таким образом, что каждый поток будет прерван один раз в executorservice.

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