Модульное тестирование неблокирующим методом (асинхронное тестирование)

У меня есть очень простой класс Check, у которого есть блокировка waitForCondition() метод. Этот метод блокирует. Я хочу создать несколько юнит-тестов для этого метода. Во-первых, метод должен возвращаться при выполнении условия. Во-вторых, метод должен вернуться, когда он прерван.

Внутри класса Check есть ArrayBlockingQueue и вызывает его метод take(), поэтому мой тест на самом деле состоит в том, чтобы правильно кодировать логику для условия (как и должно быть). В приложении данные для класса Check передаются другим потоком через InputData метод. Метод InputData выполняет логику для входящих данных и помещает фиктивный объект в ArrayBlockingQueue при выполнении условия. Это должно привести к возвращению waitForCondition().

Итак, моя первая мысль - я могу проверить InputData путем насмешки и проверить, чтобы фиктивный объект был добавлен в очередь, когда условие выполнено. Это потребовало бы изменения дизайна класса, так как очередь является частным членом данных (если только нельзя смоделировать частные данные). Вместо InputData, добавляемого непосредственно в очередь при выполнении условия, ему придется вызывать что-то, что можно смоделировать.

Но тогда возникает проблема проверки самих методов waitForCondition(), учитывая, что InputData работает правильно. Это действительно просто код:

try {
        myArrayBlockingQueue.take();
        return true;
    } catch (InterruptedException ex) {
        return false;
    }

Поэтому мне интересно, стоит ли это воображаемой проблемы: тест, который создает другой поток с Check, вызывает его waitForCondition(), а затем возвращает что-то, когда это будет сделано. Возможно, используя сервис Executor. Нечеткая часть состоит в том, как синхронизировать assertTrue(...). Я нашел эту статью об асинхронном тестировании , который выглядит так, как будто это может помочь.

Краткое содержание вопроса:

  1. Должен ли я изменить дизайн, чтобы проверить логику в InputData() и если да, то как?
  2. Должен ли я пропустить тест waitForCondition(), пока InputData() проверен?
  3. Или лучше просто сделать то, что нужно сделать (несколько сложный модульный тест), и напрямую проверить waitForCondition()?
4 голоса | спросил Pete 11 J000000Wednesday12 2012, 18:47:42

3 ответа


0

Если вы внедрите экземпляр ArrayBlockingQueue в конструктор класса Check, тогда ваш тест может ввести соответствующее значение в середине теста.

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

ответил Sean Reilly 11 J000000Wednesday12 2012, 19:15:40
0

Спасибо за приятную ссылку! Я столкнулся с некоторыми похожими проблемами, и, возможно, эта ссылка - лучший путь, чем я. (Мне также интересно посмотреть, какие еще ответы появятся на этот вопрос - это хороший вопрос)

Если вы не возражаете изменить (по крайней мере, временно ) свой фактический код (да, это не обычная практика модульного тестирования!), вы можете сделать то, что я назвал " Инъекция ошибок ".

В моей реализации вы создаете класс, который читает из свойств (или карты), чтобы «сделать что-то смешное» в определенной уникальной точке. например ваши свойства могут сказать

myClass.myMethod.blockingQueueTake = interrupt:
myClass.myLongCalculation = throw: java.lang.ArithmeticException(Failed to converge)

В своем коде вы добавляете строки тестирования, например, прямо перед вашим queue.take(), добавьте

TestSimulator.doCommand("myClass.myMethod.blockingQueueTake");

Преимущество заключается в том, что все происходит в реальном-реальном коде, а не в каком-то Mock-коде, который может стать по-настоящему проблематичным. (В моем случае SW был более старым, не написанным /не предназначенным для модульного тестирования, поэтому создание Mock было очень трудным). Недостатком является то, что вы, вероятно, захотите удалить или закомментировать код впоследствии. Так что это действительно не модульное тестирование с непрерывной интеграцией, это скорее действительно серьезная отладка. Итак, я признаю, что это далеко от идеала, но он нашел кучу ошибок для меня!

ответил user949300 11 J000000Wednesday12 2012, 19:06:56
0

Вы также можете использовать класс "test runner" для запуска утверждений в цикле. Цикл будет запускать утверждения в try /catch. Обработчик исключений просто попытается запустить утверждения еще раз, пока не истечет время ожидания. Я недавно написал в блоге об этой технике. Пример написан на Groovy, но концепция должна быть легко адаптируемой для Java.

http://www.greenmoonsoftware.com/2013/08/asynchronous -функционал-тестирование /

ответил Robert Greathouse 15 AM00000070000005531 2013, 07:02:55

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132