【问题标题】:How can I test a service provider implementation module with Junit 5?如何使用 Junit 5 测试服务提供者实现模块?
【发布时间】:2018-09-04 09:10:36
【问题描述】:

这是我的基础模块,需要实现 myspi 包中定义的接口。各种提供者可以提供 MyProvider 实现。基本模块通过 myspi.MyProvider 接口实现使用它们。

module base {
    exports myspi;
    uses myspi.MyProvider;
}

这是我的示例实现模块,它使用 MyProviderImpl 提供 MyProvider 实现

module myspi.provider {
    provides myspi.MyProvider with myspi.provider.MyProviderImpl;
}

当我在基础模块中加载实现时,所有这些都可以正常工作,

public static List<MyProvider> getMyProviders() {
        var myProviders = new ArrayList<MyProvider>();
        for (MyProvider myProvider : ServiceLoader.<MyProvider>load(MyProvider.class)) {
            myProviders.add(myProvider);
        }
        return myProviders;
    }

但同样的代码在 Junit 5 测试代码中返回空列表(ServiceLoader 返回 null)。如何使用 Junit 5 测试服务提供程序模块。或者是否有任何替代 Junit 的方法允许我们创建测试模块(模块化测试 API),在模块信息中声明“使用 myspi.MyProvider”并与 getMyProviders( )?

【问题讨论】:

  • 这值得一看 stackoverflow.com/questions/52110023/… ,Sormuras 的回答暗示了模块测试的世界是什么样子的。
  • 我已经可以为其他模块编写黑盒测试并访问它们导出的包。这里的问题是为服务提供商导出编写测试,如上所述。我无法在测试中加载服务。无论如何,我现在正在阅读 Somuras 的答案,希望能找到线索。也许我应该将实现作为一个没有模块信息的普通旧 JAR 移动,并将这个 jar 测试为一个简单的库,并使用这个库来构建服务提供者模块。但这是一个丑陋的解决方案。
  • 为什么不用new MyProviderImpl() 实例化提供程序?您要测试实现还是配置?
  • johanneslink 因为,会有不止一个 MyProviderImpl()。他们可以使用相同的 API 提供不同的数据内容,并且应用程序将允许在 3rd 第三方提供商之间切换。当然我可以测试我的单个模拟实现,但我已经在 J​​ava 9 之前完成了这些测试。在模块化之后,我想测试我的基本模块是否会找到任何第 3 方提供者,并通过基本模块实用程序类将它们绑定到我的应用程序,所以我可以使用所有这些来测试其余的基本模块 API。所以实际上我想用从提供者那里获得的内容来测试基本模块的其余部分。

标签: java service junit5 java-module java-platform-module-system


【解决方案1】:

解决了!

我已将 Junit 从 class-path 删除到 module-path,还删除了所有 Junit 4 兼容性内容,例如 RunWith() 等,并使我的测试成为纯 Junit 5 测试。

我添加了一个 module-info.java(Junit 5 不需要打开模块,尽管书上说的相反)

在我将测试模块化后,我发现它仍然没有执行 ServiceLoader 的东西。然后我开始自己寻找故障。

我找到了!在基本模块中运行 ServiceLoader 是可能的,因为基本模块引用了导出的 myProvider.jar,而后者又访问了同一目录中的 myProvider-config.properties 文件。没有这个配置文件 myProvider 不能正常工作。

另一方面,有问题的测试模块引用了 myProvider 的 eclipse 项目,而不是其导出的 .jar 文件,因此找不到其配置文件并退出。我已将此配置文件从 Netbeans 移至 Eclipse,只需将其复制到同一目录中即可。因此缺少配置文件是问题所在。

更改项目设置我可以运行测试而不会失败。

我要感谢所有回复的贡献者。

【讨论】:

【解决方案2】:

基本上你是在正确的轨道上。当解析模块是测试运行时时,您需要让 Java 模块系统相信您的测试模块是唯一的来源。

黑盒测试很容易。

模块化世界中的白盒测试,即在一个模块中测试受保护和打包私有成员,是很棘手的。至少有两种方法可以实现这一点:a) 使用 java 命令行选项在测试启动时配置 Java 模块系统或 b) 将 main 源混合到 test 源中在编译时并在您的测试源中维护一个专用的module-info.java

请访问How to make a modular build with jdk > 1.8 上发布的博客和示例的链接 为方便起见,摘录如下:

示例

背景和其他资源

并且期望大多数 IDE 也不支持您。暂时。

【讨论】:

  • 谢谢你,索莫拉斯。我已经通过上面的空指针评论访问并阅读了您的参考链接。今晚我将尝试打开测试模块,如您的一个链接和“Java 9 Modularity, Sander Mak & Paul Bakker”一书中所示。在这种情况下,我希望您能给我一个简短的答案,以运行上面的 getMyProviders() 方法。我需要它能够测试我的基本模块中的其余包。我不写任何 WhiteBox 测试,因为它们很脆弱。
【解决方案3】:

这是一篇相当老的帖子,但是如果有人在这里尝试使用带有 gradle 的 junit 5 测试 java 模块,尤其是本文中介绍的消费者/提供者,那么 Sormuras 解决方案是一种简单的方法,可以使用测试类。 它由开箱即用的 gradle-modules-plugin 支持: https://github.com/java9-modularity/gradle-modules-plugin

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2016-10-06
  • 2021-11-01
  • 1970-01-01
  • 2021-05-20
  • 2018-09-05
  • 2020-10-26
  • 1970-01-01
相关资源
最近更新 更多