[英]How do I open packages and require dependencies on test scope modules only for JUnit testing
我正在使用 java 9 jigsaw 模块将一个 jar 项目从使用 classpath 的 java 10 迁移到 java 11。 该项目有 JUnit5 测试。 测试依赖项由 maven 在测试范围内提供。 当模块被另一个项目使用时,如何打开所有包进行测试但不打开?
jar 项目只是为其他项目提供了一些类(如实用程序项目)(因此不需要主类)。
该项目在/src/main/java/a/b/c/获得了 5 个包。 使用这个 jar 的项目应该可以访问其中的 2 个。 其他 3 个仅供内部使用(由可访问的使用)。 测试位于/src/test/java/a/b/c/ 。 这些测试具有在测试范围内提供的依赖项(JUnit、mockito、junt-params),因为这些测试与使用此 jar 的项目无关
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
我在/src/main/java/提供了一个module-info.java :
module moduleName {
requires java.base;
exports a.b.c.package1;
exports a.b.c.package3;
}
所以现在包 1 和 3 中的公共类应该可以按预期被其他项目访问(我还没有能够验证这一点)。
现在运行测试会导致 java.lang.reflect.InaccessibleObjectException:无法使 abcpackage1.collections.SomeTest() 可访问:模块 moduleName 不会“打开 abcpackage1”到未命名的模块 @6a84a97d
当我打开包(打开)时,一切运行顺利。 但是现在所有的包都被打开了。 我希望包 2、4 和 5 只能在测试时访问,而 1 和 3 不应该为反射打开(因此只能导出)。
我开始想,既然 maven 告诉我未命名的模块@6a84a97d ,这可能是为测试而创建的模块。 这让我尝试在/src/test/java/添加一个module-info.java进行测试。
module moduleNameTest {
requires moduleName; // the code to test
requires java.base; // java.base could be transient on moduleName
// test dependencies
requires org.junit.jupiter.api;
requires org.junit.jupiter.params;
}
现在 maven (3.5.4) 声明:
src/test/java/module-info.java:[3,20] module not found: moduleName
src/test/java/module-info.java:[4,31] module not found: org.junit.jupiter.api
src/test/java/module-info.java:[5,31] module not found: org.junit.jupiter.params
技术:
如前所述,我希望包 2、4 和 5 只能在测试时访问,并且在使用 maven 构建 jar 时运行测试。 包 1 和包 3 应该导出用于其他项目,但不打开用于反射(因此仅导出未打开)。
如果您需要更多信息,请随时询问。
提前致谢
凯文
“欢迎在模块化世界中进行测试”,凯文。
我在这里编译了一篇关于该主题的博客: https : //github.com/sormuras/testing-in-the-modular-world
基本上,当涉及到白盒测试时,您需要在测试编译或测试运行时调整模块系统,以允许测试框架绕过模块系统障碍。
我想,你在正确的轨道上......也许 Surefire 做错了事? 想给https://github.com/sormuras/junit-platform-maven-plugin写一个截图吗? 该插件支持开箱即用的黑白盒测试。 特别是,当您提供test/java/module-info.java
测试模块描述符时,这个插件会发光。
有关如何在不触及主模块描述符的情况下组织模块化测试的信息,请参见此“图片”:
src ├── main │ └── java │ ├── foo │ │ ├── PackageFoo.java │ │ └── PublicFoo.java │ └── module-info.java <------------------ module foo { exports foo; } ├── test │ └── java .--- open module foo { │ ├── foo / exports foo; │ │ └── PackageFooTests.java / requires org.junit.jupiter.api; │ └── module-info.[java|test] <----< } └── it \\ └── bar °---- --add-reads └── src foo=org.junit.jupiter.api └── test --add-opens └── java foo/foo=org.junit.platform.commons ├── bar │ └── PublicFooTests.java └── module-info.java <------ open module bar { requires foo; requires org.junit.jupiter.api; }
这种模式也应该很容易被你的设置采用。
相关问题: 如何在模块化 Java 项目中组织测试?
如果将 junit 打包为 java9 模块,则问题可能已经解决。 比你的错误会变成类似的东西
“无法使 abcpackage1.collections.SomeTest() 可访问:模块 moduleName 不会“打开 abcpackage1”到junit5模块 @6a84a97d
在这种情况下,您可以将它打开到junit5模块(或任何试图在您的类上使用反射的“命名”测试模块)。 由于目前我认为情况并非如此(junit5 从 Java 的角度来看属于未命名模块),您的替代选择是
将测试移动到单独的 maven 模块。 您将有两个 Maven 模块yourModule-1.0
和yourModule-tests-1.0
。 yourModule-tests-1.0
将取决于yourModule-1.0
,因此在 maven 中它会构建。 然后你可以只打开你的测试模块进行反射,在你的module-info.java
使用open module moduleNameTest {}
。 您的主模块仍将受到保护。
带有一些“前缀包”的测试的前缀包,所以代替abcpackage1.collections.SomeTest()
你会有abcmytests.package1.collections.SomeTest()
。 然后当你只打开你的测试包abcmytests.package1.collections.SomeTest()
进行反射,同时保持你的主源安全,因为它保留在另一个包中
您现在可以接受它,只需使用opens abcpackage1.collections.SomeTest()
打开您的包。 除非你在某个共享库上工作,否则没有人可能想在你的代码上使用反射。
根据第 3 点的假设,最简单的方法是打开整个模块进行反射,将其声明为open module moduleName {}
而不是 ' module moduleName {}
。 这样,您每次在尚未打开的包中创建测试时都不需要调整module-info.java
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.