通过集成测试,我的意思是实例化捆绑的一个子集,以自动验证该子系统中的功能.
我们正在运行Equinox并使用Eclipse作为工具链. Eclipse提供了“运行为JUnit插件”选项,它使OSGi框架启动并实例化配置包,因此我猜想这是要遵循的路径,但是我没有找到一种将DS引用注入到我的测试中的方法.
我已经看到使用ServiceTracker作为访问不同服务包的编程方式,但是这样做的目的是让DS不是吗?
我刚刚开始使用OSGI,所以我想我只是想一些拼图,让我把我的多捆绑测试放在一起.
有任何想法吗?
谢谢Gerard.
*编辑:解决方案*
在进一步研究这个问题之后,我终于弄清楚如何使用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使用声明的onServiceUp方法注入对FooService的依赖关系. onServiceDown必须在运行测试后的OSGi关闭阶段中被调用.
com.test.functionaltest.MyTester包含要执行的测试方法,遵循典型的JUnit实践.
到这里,这是所有的“由书”.但是,如果Junit运行,则在访问FooService的引用时会抛出NullPointerException.原因是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服务注入依赖关系,或者在超时后失败.
花了我一段时间才能完全弄清楚这一点.我希望将来可以为同行程序员节省一些头痛.