OSGi单元测试和Bundle导出

6
什么是平衡包的声明导出和单元测试需求的最佳方式?
考虑一个名为“mybundle”的捆绑包,您想编写单元测试。该捆绑包的源代码存储在IDE的“项目”概念中。例如:
mybundle
  src/java
    mybundle.package1
      ...java
  bnd.bnd

我指的是针对个人POJO的单元测试,与这些类在bundle中使用时所处的更广泛的OSGi上下文无关。在可能的情况下,测试应该能够使用“普通”的类加载运行,例如通过Eclipse中的JUnit运行器。
在开发时,有几种方法可以打包单元测试:

Bundle源代码中的单元测试

在这里,将单元测试添加到项目中的源文件夹中:
mybundle
  src/java
    mybundle.package1
      ...java
  test/java
    mybundle.package1.test
      ...java
  bnd.bnd

请注意附加的“.test”以区分包并避免拆分包问题。
通常会采取一些措施确保测试类不会出现在构建的捆绑JAR中。
在单独的包中进行单元测试
在这里添加了一个单独的包,名称后缀为“.test”,这是一般惯例。
mybundle
  src/java
    mybundle.package1
      ...java
mybundle.test
  test/java
    mybundle.package1.test
      ...java
  bnd.bnd

这样做的问题在于,由于类是分离的,并且单元测试的运行可能不了解OSGi环境(例如使用Eclipse JUnit运行程序),因此您需要装饰JUnit运行程序的运行时类路径。

片段中的单元测试

(感谢@HollyCummins)。 这里创建了一个单独的bundle片段:
mybundle.fragment
  test/java
    mybundle.package1.test
      ...java
  bnd.bnd

该片段将“mybundle”声明为其主机,从而允许它共享“mybundle”中的类,无需导出包。
缺点是,由于片段加载是一个OSGi概念,因此您需要在OSGi容器中运行或装饰类路径。
出口问题
当考虑如何执行Export-Package时,问题就出现了。认为尽可能少地导出包是一种良好的做法。但是似乎单元测试会强制导出额外的包。
这对于第二个选项最为明显,即具有单独的测试包。测试包中的测试必须Import-Package下的类,而要测试的包也必须Export-Package所有所述类。
因此,明显的解决方案是倾向于在包源中进行单元测试,但是在非平凡情况下很快会出现问题。您可能希望共享测试代码,例如,您可能在单独的包中进行OSGi集成测试。为了共享代码,您最终不得不Export-Package测试包,然后当然还会在构建的包中使用测试代码!
什么是组织OSGi bundles / projects进行测试的最佳方法?

1
第三个选项是在单元测试中使用片段(fragment)。这样可以确保您的测试与要被测试的代码共享一个类加载器,因此不需要额外导出内部包的包。如果需要,测试片段甚至可以导出主要捆绑包的内部包。该片段将有自己的包导入,因此它可以引入共享的测试代码,而不会污染主要捆绑包的包导入。 - Holly Cummins
@HollyCummins 很好的想法!如果有效的话,将该评论推广为答案可能是值得的。我目前正在使用的 bndtools(助手)目前不支持在 v2 alpha 中解析片段,因此我无法进行测试,所以我必须等到可以尝试它。 - Dan Gravell
实际上,如果这些是针对POJO的单元测试(因为我目前最感兴趣),而不是使用OSGi框架的集成测试,那么我还需要在运行路径中装饰被测试源,对吧?我会在问题中添加一些澄清以及您的其他建议。 - Dan Gravell
3个回答

0
如果您正在进行单元测试,而且是在完全隔离的情况下(就像许多单元测试通常所做的那样),为什么还要在OSGi框架中打包和运行这些单元测试呢?只需编译类,编译相应的测试类,并在您喜欢的任何测试框架中运行它们即可。

0
第三个选项是使用OSGi片段进行单元测试。这可以确保您的测试与要测试的代码共享类加载器,因此无需额外导出内部包。如果需要,测试片段甚至可以导出主要捆绑包的内部包。该片段将具有自己的包导入,因此它可以拉取共享测试代码,而不会污染主要捆绑包的包导入。
如上面的评论所提到的并更新了原始问题,使用片段仍然会让您对如何处理构建和类路径产生一些疑问。如果您在OSGi容器之外运行测试,则片段的类加载器优势基本上消失了,除非您在IDE中引入了导入的测试依赖项。
如果您在OSGi容器中运行测试,则片段与普通捆绑包相比具有一些缺点,这可能是一个问题,具体取决于您如何驱动测试。片段无法声明Activator,因为它们没有独立的生命周期。虽然Blueprint服务通常可以,但声明式服务不能以自然方式从片段中注册。

0

使用 Maven 将使选项 1 的实现变得非常简单。优点是 Maven 为您管理类路径, 因此仅在测试中需要的代码或依赖项不会出现在最终捆绑包中。您甚至可以将单元测试放置在与受测试类相同的包中,以便从测试中访问包私有类。由于测试是使用正常的类加载执行的,因此 Export-Packages 对其没有任何影响。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接