如何使用 Junit 5 测试服务提供者实现模块?

How can I test a service provider implementation module with Junit 5?

这是我的基础模块,需要实现 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 测试代码中的相同代码 returns 空列表 (ServiceLoader returns null)。我如何使用 Junit 5 测试服务提供者模块。或者是否有任何替代 Junit 的方法允许我们创建测试模块(模块化测试 API),在模块信息中声明 "uses myspi.MyProvider" 并且工作正常使用 getMyProviders()?

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

黑盒测试很容易。

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

请访问 上发布的博客和示例链接 为方便起见,摘录如下:

例子

背景和其他资源

并且预计大多数 IDE 也不支持你。现在。

已解决!

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

我已经添加了一个模块-info.java(Junit 5 不需要一个开放的模块,尽管书中的说法恰恰相反)

在我将测试模块化后,我发现它仍然不执行 ServiceLoader 的东西。然后我就开始自己找问题了。

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

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

更改项目设置我可以 运行 测试没有任何失败。

感谢所有回复的贡献者。

这是一个很旧的 post 但是如果有人来到这里尝试使用 gradle 测试 java junit 5 模块,尤其是本文中介绍的 consumer/provider post,Sormuras 解决方案是简单的方法,用测试 类 修补消费者模块。 它由 gradle-modules-plugin 支持,开箱即用: https://github.com/java9-modularity/gradle-modules-plugin