Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
327 views
in Technique[技术] by (71.8m points)

java - How do I open packages and require dependencies on test scope modules only for JUnit testing

I'm migrating a jar project from java 10 using classpath to java 11 using the java 9 jigsaw modules. There are JUnit5 tests for the project. The test dependencies are provided at test scope by maven. How to make all packages open for testing but not open when the module is used by another project?

The jar project is just providing a few classes (like a utility project) for other projects (so no main class needed).

The project got 5 packages at /src/main/java/a/b/c/. 2 of them should be accessible for projects using this jar. The other 3 are for internal use only (used by the accessible ones). The tests are located at /src/test/java/a/b/c/. These tests have dependencies (JUnit, mockito, junt-params) provided in test scope, since the tests are not relevant for the projects using this jar

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>

I have provided a module-info.java at /src/main/java/ :

module moduleName {

requires java.base;

exports a.b.c.package1;
exports a.b.c.package3;
}

so now the public classes in package 1 and 3 should be accessible to other projects as expected (I have not been able to verify this yet).

Running the Tests now results in java.lang.reflect.InaccessibleObjectException: Unable to make a.b.c.package1.collections.SomeTest() accessible: module moduleName does not "opens a.b.c.package1" to unnamed module @6a84a97d

when I open the packages (with opens) everything runs smooth. But now all packages are now opened. I expect package 2, 4 and 5 to be only accessible while testing and 1 and 3 should not be open for reflection (so only exported).

I came to think, since maven tells me unnamed module @6a84a97d, this might be a module created for testing. That made me try adding a module-info.java at /src/test/java/ for testing.

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;
}

now maven (3.5.4) states:

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

Technologies:

  • java openJDK 11
  • mvn 3.5.4
  • JUnit 5.3.0
  • Surefire Plugin 3.0.0-M3
  • mockito 2.21.0

As stated earlier I expect package 2, 4 and 5 to be only accessible while testing and the tests to be run on building the jar with maven. Package 1 and 3 should be exported for use in other projects but not open for reflection (so only exported not opened).

If you need additional information don't hesitate to ask.

Thanks in Advance

Kevin

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

"Welcome to Testing In The Modular World", Kevin.

I compiled a blog about that topic here: https://github.com/sormuras/testing-in-the-modular-world

Basically, when it comes to white-box testing, you need to tweak the module system either at test compile or test runtime to allow testing frameworks to by-pass the module system barriers.

I guess, you're on the right track ... maybe Surefire does the wrong thing? Want to give https://github.com/sormuras/junit-platform-maven-plugin I wrote a shot? This plugin supports black- and white-box testing out of the box. Especially, this plugin shines, when you provide a test/java/module-info.java test module descriptor.

See this "picture" for how to organize modular tests without touching the main module descriptor:

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; }

This pattern should be easy to adopt to your setup as well.

Related question: How do you organize tests in a modular Java project?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...