Я пытаюсь выяснить, как реализовать тест интеграции нескольких пакетов в OSGi с использованием JUnit.
Под интеграционным тестом я имею в виду создание экземпляра подмножества пакетов для автоматической проверки функциональности в этой подсистеме.
Мы запускаем Equinox и используем Eclipse в качестве цепочки инструментов. Eclipse предлагает опцию «Run as JUnit Plug-in», которая поднимает платформу OSGi и создает экземпляры пакетов конфигурации, так что я думаю, что это путь, по которому нужно следовать, но я не нахожу способ внедрить ссылки DS в мои тесты.
Я видел использование ServiceTracker в качестве программного средства для доступа к различным пакетам услуг, но это лучше, чем иметь DS, не так ли?
Я только начинаю работать с OSGI, поэтому я полагаю, что мне не хватает какой-то части головоломки, которая позволила бы мне собрать мои тесты из нескольких пакетов.
Есть идеи?
Спасибо, Джерард.
* РЕДАКТИРОВАТЬ: РЕШЕНИЕ *
После более подробного изучения этой проблемы я, наконец, выяснил, как внедрить эти тесты интеграции с несколькими пакетами с помощью функции подключаемого модуля JUnit:
Чтобы внедрение динамических служб работало, необходимо создать файл определения службы, в котором должны быть объявлены внедренные зависимости, как это обычно делается при работе с DS.
Этот файл (обычно) находится в каталоге OSGI-INF/
. например OSGI-INF/service.xml
service.xml должен объявить необходимые зависимости для этого теста, но не предлагает собственную службу:
service.xml
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="MyTest" activate="startup" deactivate="shutdown">
<implementation class="com.test.functionaltest.MyTester"/>
<reference name="OtherService" interface="com.product.service.FooService" policy="static" cardinality="1..1" bind="onServiceUp" unbind="onServiceDown"/>
</scr:component>
Это будет указывать DS вводить зависимость от FooService, используя объявленный метод onServiceUp. onServiceDown должен быть реализован так, как он вызывается во время фазы выключения OSGi после запуска тестов.
com.test.functionaltest.MyTester содержит методы тестирования, которые должны быть выполнены, следуя типичным практикам JUnit.
Здесь все по книге. Тем не менее, если Junit запущен, он выдаст исключение NullPointerException при доступе к ссылке на FooService. Причина этого заключается в том, что платформа OSGi находится в состоянии гонки с контекстом выполнения тестов JUnit, и обычно тестовый запуск Junit выигрывает эту гонку, выполняя тесты до введения ссылки на требуемую службу.
Чтобы разрешить эту ситуацию, необходимо выполнить тест Junit, чтобы дождаться, пока среда выполнения OSGi выполнит свою работу. Я решил эту проблему с помощью CountDownLatch, который инициализируется количеством зависимых сервисов, необходимых в тесте.
Затем каждый метод внедрения зависимостей ведет обратный отсчет, и когда все они будут выполнены, тест начнется. Код выглядит так:
private static CountDownLatch dependencyLatch = new CountDownLatch(1);// 1 = number of dependencies required
static FooService fooService = null;
public void onFooServiceUp(FooService service) {
fooService = service;
dependencyLatch.countDown();
}
Обратите внимание, что ссылка fooService
должна быть статической, чтобы разрешить разделение ссылки на службу между контекстами выполнения OSGi и JUnit. CountDownLatch предоставляет механизм синхронизации высокого уровня для безопасной публикации этой общей ссылки.
Затем перед выполнением теста необходимо добавить проверку зависимостей:
@Before
public void dependencyCheck() {
// Wait for OSGi dependencies
try {
dependencyLatch.await(10, TimeUnit.SECONDS);
// Dependencies fulfilled
} catch (InterruptedException ex) {
fail("OSGi dependencies unfulfilled");
}
}
Таким образом, инфраструктура Junit ожидает, пока служба OSGi DS не введет зависимости, или произойдет сбой по истечении времени ожидания.
Мне потребовалось довольно много времени, чтобы полностью понять это. Я надеюсь, что в будущем это избавит коллег от программистов.