如何打开包并仅要求依赖于测试范围模块以进行 JUnit 测试
How do I open packages and require dependencies on test scope modules only for JUnit testing
我正在使用 classpath 将一个 jar 项目从 java 10 迁移到使用 java 9 jigsaw 模块的 java 11。
该项目有 JUnit5 测试。
测试依赖项由 Maven 在测试范围内提供。
如何让所有包都打开测试,模块被其他项目使用时不打开?
jar 项目只是为其他项目提供一些 classes(如实用项目)(因此不需要主要 class)。
该项目在 /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/ 提供了一个 模块-info.java :
module moduleName {
requires java.base;
exports a.b.c.package1;
exports a.b.c.package3;
}
所以现在包 1 和包 3 中的 public classes 应该可以按预期被其他项目访问(我还没有能够验证这一点)。
运行 测试现在导致 java.lang.reflect.InaccessibleObjectException:无法使 a.b.c.package1.collections.SomeTest() 可访问:模块 moduleName 不会 "opens a.b.c.package1" 未命名模块@6a84a97d
当我打开包裹时(打开)一切都运行很顺利。
但是现在所有的包都打开了。
我希望包 2、4 和 5 只能在测试时访问,而 1 和 3 不应该为反射打开(所以只导出)。
我想,既然maven告诉我unnamed module @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
技术:
- java openJDK 11
- mvn 3.5.4
- JUnit 5.3.0
- Surefire 插件 3.0.0-M3
- 模拟 2.21.0
如前所述,我希望包 2、4 和 5 只能在测试时访问,并且测试 运行 在使用 Maven 构建 jar 时。包 1 和 3 应该导出用于其他项目但不打开反射(所以只导出不打开)。
如果您需要更多信息,请随时询问。
提前致谢
凯文
"Welcome to Testing In The Modular World",凯文。
我在这里编写了一篇关于该主题的博客:https://github.com/sormuras/testing-in-the-modular-world
基本上,当涉及到白盒测试时,您需要在 test compile 或 test runtime 调整模块系统允许测试框架绕过模块系统障碍。
我想,您的方向是对的……也许 Surefire 做错了事?想给https://github.com/sormuras/junit-platform-maven-plugin我写个镜头吗?该插件支持开箱即用的黑盒和白盒测试。特别是,当您提供 test/java/module-info.java
测试模块描述符时,这个插件会大放异彩。
请参阅此"picture"了解如何组织模块化测试而不触及主模块描述符:
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;
}
这种模式也应该很容易应用到您的设置中。
相关问题:
如果将 junit 打包为 java9 模块,问题本可以解决。比你的错误会变成类似
“无法使 a.b.c.package1.collections.SomeTest() 可访问:模块 moduleName 不会“打开 a.b.c.package1”到 junit5模块@6a84a97d
在这种情况下,您可以将它打开到 junit5 模块(或任何试图在您的 类 上使用反射的“命名”测试模块)。由于目前我认为情况并非如此(从 java 的角度来看,junit5 属于未命名模块),您的替代选择是
将测试移动到单独的 Maven 模块。您将有两个 Maven 模块 yourModule-1.0
和 yourModule-tests-1.0
。 yourModule-tests-1.0
将取决于 yourModule-1.0
,因此在 Maven 中它会构建。然后你可以在你的 module-info.java
中使用 open module moduleNameTest {}
只打开你的测试模块进行反射。您的主模块仍将受到保护。
prefix package with tests with some "prefix-package",所以 a.b.c.package1.collections.SomeTest()
你会 a.b.c.mytests.package1.collections.SomeTest()
。然后当你只打开你的测试包 a.b.c.mytests.package1.collections.SomeTest()
进行反射时,同时保持你的主要源安全,因为它仍然在另一个包中
您现在可以接受它,只需使用 opens a.b.c.package1.collections.SomeTest()
打开您的包裹即可。除非你在一些共享库上工作,否则没有人可能想在你的代码上使用反射。
根据第 3 点的假设。最简单的方法是打开整个模块进行反射,将其声明为 open module moduleName {}
而不仅仅是 'module moduleName {}
。这样您就不需要每次在尚未打开的包中创建测试时都调整 module-info.java
。
我正在使用 classpath 将一个 jar 项目从 java 10 迁移到使用 java 9 jigsaw 模块的 java 11。 该项目有 JUnit5 测试。 测试依赖项由 Maven 在测试范围内提供。 如何让所有包都打开测试,模块被其他项目使用时不打开?
jar 项目只是为其他项目提供一些 classes(如实用项目)(因此不需要主要 class)。
该项目在 /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/ 提供了一个 模块-info.java :
module moduleName {
requires java.base;
exports a.b.c.package1;
exports a.b.c.package3;
}
所以现在包 1 和包 3 中的 public classes 应该可以按预期被其他项目访问(我还没有能够验证这一点)。
运行 测试现在导致 java.lang.reflect.InaccessibleObjectException:无法使 a.b.c.package1.collections.SomeTest() 可访问:模块 moduleName 不会 "opens a.b.c.package1" 未命名模块@6a84a97d
当我打开包裹时(打开)一切都运行很顺利。 但是现在所有的包都打开了。 我希望包 2、4 和 5 只能在测试时访问,而 1 和 3 不应该为反射打开(所以只导出)。
我想,既然maven告诉我unnamed module @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
技术:
- java openJDK 11
- mvn 3.5.4
- JUnit 5.3.0
- Surefire 插件 3.0.0-M3
- 模拟 2.21.0
如前所述,我希望包 2、4 和 5 只能在测试时访问,并且测试 运行 在使用 Maven 构建 jar 时。包 1 和 3 应该导出用于其他项目但不打开反射(所以只导出不打开)。
如果您需要更多信息,请随时询问。
提前致谢
凯文
"Welcome to Testing In The Modular World",凯文。
我在这里编写了一篇关于该主题的博客:https://github.com/sormuras/testing-in-the-modular-world
基本上,当涉及到白盒测试时,您需要在 test compile 或 test runtime 调整模块系统允许测试框架绕过模块系统障碍。
我想,您的方向是对的……也许 Surefire 做错了事?想给https://github.com/sormuras/junit-platform-maven-plugin我写个镜头吗?该插件支持开箱即用的黑盒和白盒测试。特别是,当您提供 test/java/module-info.java
测试模块描述符时,这个插件会大放异彩。
请参阅此"picture"了解如何组织模块化测试而不触及主模块描述符:
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;
}
这种模式也应该很容易应用到您的设置中。
相关问题:
如果将 junit 打包为 java9 模块,问题本可以解决。比你的错误会变成类似
“无法使 a.b.c.package1.collections.SomeTest() 可访问:模块 moduleName 不会“打开 a.b.c.package1”到 junit5模块@6a84a97d
在这种情况下,您可以将它打开到 junit5 模块(或任何试图在您的 类 上使用反射的“命名”测试模块)。由于目前我认为情况并非如此(从 java 的角度来看,junit5 属于未命名模块),您的替代选择是
将测试移动到单独的 Maven 模块。您将有两个 Maven 模块
yourModule-1.0
和yourModule-tests-1.0
。yourModule-tests-1.0
将取决于yourModule-1.0
,因此在 Maven 中它会构建。然后你可以在你的module-info.java
中使用open module moduleNameTest {}
只打开你的测试模块进行反射。您的主模块仍将受到保护。prefix package with tests with some "prefix-package",所以
a.b.c.package1.collections.SomeTest()
你会a.b.c.mytests.package1.collections.SomeTest()
。然后当你只打开你的测试包a.b.c.mytests.package1.collections.SomeTest()
进行反射时,同时保持你的主要源安全,因为它仍然在另一个包中您现在可以接受它,只需使用
opens a.b.c.package1.collections.SomeTest()
打开您的包裹即可。除非你在一些共享库上工作,否则没有人可能想在你的代码上使用反射。根据第 3 点的假设。最简单的方法是打开整个模块进行反射,将其声明为
open module moduleName {}
而不仅仅是 'module moduleName {}
。这样您就不需要每次在尚未打开的包中创建测试时都调整module-info.java
。