OSGi enRoute – 2.2_9 – 在 OSGi中进行测试

本节中你将学到什么

在本节中我们定义了在真实的OSGi框架中运行的测试。OSGi测试会启动一个配置好的框架,然后执行一个JUnit Runner来运行测试。测试框架与Eclipse 的JUnit支持特性已经完全集成了,它们工作起来几乎完全一致。

OSGi JUnit测试的目的在于对服务契约进行测试;一般来说它用于测试某个Provider是否满足了服务契约的要求。这意味着这些测试是黑盒测试;对于它们的内部情况我们并不了解。

如果你根据之前的章节正在运行着框架,那么现在可以停止框架了。在本节中我们将运行自动化测试。

OSGi JUnit测试

OSGi JUnit测试是一个新的工程。因此创建一个com.acme.prime.eval.test工程,确保使用OSGi enRoute模板。由于此工程的后缀是.test,所以会自动进行测试相关的设置。

20171217_001

在OSGi Test工程中你将在src文件夹中进行工作,而不是在test文件夹中进行工作,因为我们创建的是一个test bundle,这可能会造成一点点困惑;如果我们使用test源码文件夹则最终在bundle中不会有任何类。在test文件夹中的类不会被添加到JAR文件中。

OSGi enRoute模板已经生成了一个简单的测试用例,它给出了一个Bundle Context,不过测试用例尚未使用我们的服务。

 

那么我们如何获取Eval服务来进行测试呢?这会有些麻烦,因为我们没有得到DS的支持。唉,回到必须通过手工来获取服务的旧时光吧:

当然,这会导致service tracker被暴露出来,但是对于测试用例来说,这并不算多大的问题。现在如果要判断我们的服务是否存在需要添加一个测试。

然而,如果添加了这些代码,我们会发现Eclipse找不到Eval类。还记得这个问题吗?我们需要将com.acme.prime.eval.api工程添加到我们的build path中。双击bnd.bnd文件,选择Build然后添加com.acme.prime.eval.api工程。只要保存了bnd.bnd文件,我们就可以导入Eval类并移除对应的错误。记住当前的Provider还导出了com.acme.prime.eval.api包。在Classpath中添加一个实现bundle是一个不好的实践:永远使用服务契约来进行编译。

我们几乎已经为运行测试做好了准备。不过在开始测试之前,让我们来审视一下我们的Runtime。我们的环境应该是如何的呢?进入bnd.bnd文件的Run选项卡。初始的Requirement清单中包含了com.acme.prime.eval.test工程。

在resolve过程中,清单中会增加provider,因为它带有API和需要的JUnit bundle。

点击Resolve按钮并保存。我们仅需要很少量的依赖,因为provider使用了Declarative Services (DS) ,又名SCR。

我们的bundle现在看起来如下图所示:

20171217_002

如果要运行测试我们可以选择下列之内容之一: com.acme.prime.eval.test工程、它的src文件夹、此文件夹中的包、此包中的一个类、此类中的一个方法,或者是bnd.bnd文件。然后我们可以选择右键菜单@/Debug As/Bnd OSGi Test Launcher (JUnit) 或者快捷键(Shift+Alt+X C)。这将会在指定的范围内执行测试。测试结果将会在标准的Junit视图中进行报告。还记得飞行员和起落架的类比吗?要打赌你会不会将JUnit Test和Bnd OSGi Test Launcher (JUnit)的入口混淆吗?或者更坏的情况是你可能会选择Bnd OSGi Run Launcher。如果你选择了后者,你将会获得一个由于JUnit缺失导致bundle无法解析的错误信息。

然后…是熟悉的绿色进度条!

20171217_003

测试&调试

目前的测试仅测试了服务是否存在。现在让我们来添加更多的内容:

测试都运行在一个真实的OSGi框架中,不过这些并不会阻止我们进行调试。点击trig函数左边的空白处(译者注:即添加一个断点),选择函数名称,然后选择右键菜单 @/Debug As/Bnd OSGi Test Launcher (JUnit) (Shift+Alt+D K)。调试器会运行到方法内部,然后你就可以开始进行单步调试了,甚至可以跟踪进入到其他的bundle。

如果你进行了修改,在这种情况下修改并不会马上在运行的框架中得到体现。

它是如何工作的?

Test bundle都是普通的bundle,但是它们带有特殊的header:Test-Cases。这个header中包含了一个带有JUnit测试用例的类名清单。如果你查看bnd.bnd文件的Source选项卡则会看到这个header看起来如下所示:

${test-cases}宏指令由OSGi enRoute进行设置;它会查找继承了junit.framework.TestCase类或使用了类似@Test的JUnit4注解(你不能混合使用这两种机制)的类。在本例中如下所示:

你可以通过双击generated/com.acme.prime.eval.test.jar并查看Manifest中的Test-Cases header来进行检验。

当你运行一个OSGi Junit测试时,bnd将会创建一个新的带有指定运行bundle的框架。在此框架的ClassPath中还会添加一个aQute.junit bundle以及所有在-testpath中列出的JAR。所有可以用于运行框架的配置都可以用于运行测试,例如:-runproperties和 -runtrace。

在所有的bundle都启动之后,aQute.junit bundle将会扫描所有的bundle查找Test-Cases header。它将会加载这些类并运行其中的测试。

如果测试是通过Eclipse JUnit framework启动的,则运行模式会有一点点不同。bnd会设置一个新的框架,但是它会传递由Eclipse根据选择的内容决定的类/方法集。例如,在一个包中的所有测试用例。然后aQuite.junit会仅执行这些类/方法,并且将结果报告给Eclipse并在JUnit View中进行展示。

 

打赏一下
支付宝
微信
除非注明,博客文章均为原创,转载请标明文章地址
本文地址: http://www.javafxchina.net/blog/2017/12/osgi-enroute-0202-09/
百度已收录