【发布时间】:2020-03-17 15:46:10
【问题描述】:
我有一个模拟类,其中包含我从模块提供的服务的简单实现。我正在使用 OpenJDK 11.03、gradle 5.2.1 和 IntelliJ 2019.2。
在/main/code/myPackage/myService.java 我有:
package myPackage;
class myService {
public abstract void someFunction();
}
在我的test/code/somePackage/myMockService 我有:
package myPackage;
// no import, they're in the same package.
class myMockService extends myService {
@Override
public void someFunction() { System.out.prinln("Hello World"); }
}
在我的main/code/module-info.java 我有:
module myModule {
exports somePackage;
}
我在test/code/module-info.java 上尝试了几种变体,但均未成功。例如:
// "open module" lets anyone use reflection within (mostly JUnit 5 in my case)
import myPackage.myService;
import myPackage.myMockService;
open module myTestModule {
exports myPackage;
provides myService with myMockService
}
上面的module-info.java 引发了关于“模块名称 myTestModule 与预期名称 myModule 不匹配”、“包 'myPackage' 不可见”(来自 myMockModule.java)的错误,解释了“包 myPackage 在模块 myModule 中声明但模块 myTestModule 没有读取它”
另一方面,使用以下module-info.java,我得到了不同批次的错误(代码下方)
import myPackage.myService;
import myPackage.myMockService;
open module myModule {
provides myService with myMockService;
}
如果没有requires myModule;,我的测试代码中对主代码分支的每次引用都会给出“错误:找不到符号”。 requires myModule;,我得到一个“错误:涉及 myModule 的循环依赖”。
所以...我的测试不能在不同的模块中。而且它们不能是同一个模块! [删除一长串脏话]
-
如何在测试代码中引入服务的模拟版本,而不是创建完全不同的模块/gradle 子项目?
-
或者这只是一个不可能的情况,虽然您可以拥有一个单独的测试模块信息,但您不能用它做很多事情?
-
或者有没有办法在运行时动态加载东西,这样我就不必把每一个小模拟服务放在任何模块信息、测试或其他地方?这样
ServiceLoader.load()就会找到它们。嗯...也许扩展ServiceLoader并将其用法包装在主代码中,以便在生产代码或测试代码中使用正确的...
【问题讨论】:
-
我在
src/main/java中只有一个module-info.java文件。如果(假设)它不会包含在您的构建中,为什么您的测试目录需要一个? -
它将在测试中使用。我们完全是模块化的,并且能够启动一个微不足道的模拟服务似乎并不是太简单......我正在尝试测试。
-
有点跑题了,但这个问题向我揭示了这里的 java 着色代码不知道:模块、打开、导出、提供、使用和几乎肯定是“到”。
-
您绝对可以为您的测试代码设置一个单独的
module-info,但我相信它只适用于“黑盒测试”,因为不允许拆分包。你能创建一个minimal reproducible example 来演示问题,包括build.gradle文件吗? -
嗯,我大部分想通了。见下文。
标签: java mocking junit5 openjdk-11