Услуги OSGi пригодятся для разработки систем на основе слабосвязанных компонентов. Но слабая связь может затруднить распознавание проблем, связанных с привязкой сервисных ссылок. Таким образом, мы обычно запускаем интеграционные тесты для обеспечения доступности сервисных компонентов во время выполнения.
Чтобы уменьшить количество шаблонов, необходимых для такого рода тестов, я написал простой служебный класс для получения конкретных реализаций сервиса. Поскольку это также может быть полезно для других людей, я решил предоставить краткое описание использования в этом посте.
OSGi Сервисные отношения
Службы OSGi могут зависеть или использовать другие компоненты для достижения своей цели. И сеть отношений в работающей системе может быть довольно сложной. Это может иногда затруднять выяснение того, почему определенные функции приложения не работают должным образом.
Рассмотрим компонент, который уведомляет другие компоненты, например, используя шаблон доски . В случае, если один из наблюдателей не сможет зарегистрироваться, уведомление не произойдет, и зависимые возможности могут быть нарушены.
Хотя причина этой проблемы может быть тривиальной — например, отсутствующее объявление компонента в MANIFEST.MF
— может пройти некоторое время, прежде чем он будет обнаружен. Поэтому представляется хорошей идеей предотвратить эти проблемы с помощью интеграционных тестов.
Такие тесты запускаются после процесса сборки системы, запускают тестируемый комплект в соответствующей среде OSGi и проверяют его правильный вклад компонента во время выполнения.
Для общих целей тестирования OSGi на GitHub существует проект OSGi Testing Utils . Однако я не смог написать простой однострочный текст, используя эту библиотеку, чтобы извлечь конкретную реализацию сервиса из реестра. Вот почему я написал служебный класс, описанный в этом посте. Но, как всегда, есть хороший шанс, что я просто был слишком глуп, чтобы найти правильное решение …
ServiceCollector
Предположим, у нас есть компонент типа Service
…
1
2
3
4
|
// Service API declaration interface Service { [...] } |
… и комплект, обеспечивающий соответствующий класс реализации …
1
2
3
4
5
6
|
// Service implementation provided by another bundle public class ServiceImpl implements Service { [...] } |
… Который зарегистрирован через декларативные услуги :
01
02
03
04
05
06
07
08
09
10
|
<? xml version = "1.0" encoding = "UTF-8" ?> < scr:component immediate = "true" name = "Implementation of Service API" > < implementation class = "com.codeaffine.example.core.ServiceImpl" /> < service < <provide interface = "com.codeaffine.example.api.Service" /> </ service > </ scr:component > |
Чтобы убедиться, что пакет действительно успешно регистрирует экземпляр ServiceImpl
, тест может извлечь компоненты типа Service
из реестра во время выполнения и каким-то образом отфильтровать вклад нашего конкретного компонента. Что в принципе и делает ServiceCollector
.
Однако я использую практический подход для поиска только конкретной реализации. Хотя это может быть неубедительным в редких условиях (несколько сервисов одного типа реализации, предоставляемых различными пакетами или тому подобным), это прямо для случаев использования, с которыми мы сталкиваемся в нашей повседневной работе.
1
2
3
4
5
6
|
@Test public void serviceAvailable() { List services = collectServices( Service. class , ServiceImpl. class ); assertThat( services ).hasSize( 1 ); } |
Как вы можете видеть, ServiceCollector#collectServices
принимает объявление службы и тип ее реализации в качестве параметра для поиска доступных экземпляров службы, предоставленных пакетом во время выполнения. Он возвращает список компонентов, поскольку могут быть зарегистрированы несколько экземпляров службы, соответствующих типу реализации.
Вывод
До сих пор ServiceCollector
оказался весьма полезным в нашем текущем проекте. Прежде чем писать какие-либо тесты, связанные с функциональностью, при создании нового сервиса, первое, что мы обычно делаем, это проверяем доступность сервиса — что является легкой задачей с маленьким помощником.
Но еще раз обратите внимание, что предполагаемое использование — это сценарий тестирования интеграции услуг-вкладов-на-пакет . Поэтому будьте осторожны, например, с несколькими экземплярами конкретной реализации, предоставляемой different
пакетами. Такие ситуации вызывают нежелательное соединение тестов, связанных с комплектом.
ServiceCollector
является частью функции com.codeaffine.osgi.test.util репозитория Xiled P2: http://fappel.github.io/xiliary
Если вы хотите взглянуть на код или подать проблему, вы также можете взглянуть на проект Xiled GitHub: https://github.com/fappel/xiliary
Для всего остального не стесняйтесь использовать раздел комментариев ниже. Так что следите за обновлениями — в следующий раз, когда я представлю еще одного помощника этого пакета, правило JUnit, полезное для регистрации тестовых сервисов …
Ссылка: | Помощник по тестированию услуг OSGi: ServiceCollector от нашего партнера по JCG Фрэнка Аппеля в блоге Code Affine . |