How to test within the same module? - java

In this project I have a modular setup. There is a parent with two modules in it.
Here's a snippet from the parent-pom.xml:
<modules>
<module>moduleA</module>
<module>moduleB</module>
</modules>
Both modules have a module-info.java. Here is the module-info.java for moduleB:
module moduleB {
requires spring.web;
requires static lombok;
requires java.validation;
requires swagger.annotations;
requires slf4j.api;
exports com.example.service
}
Within moduleB there is the main folder and the test folder, like any regular java project. Within the test-folder there is a JUnit5 test, which is trying to test a service within the same package, but in the src-folder.
While trying to attempt this, I get the following error-message:
module moduleB does not "opens com.example.service" to unnamed module #67205a84
As I understand, all of the dependencies which are not part of the module will be packaged in an 'unnamed' module. In this case module #67205a84. Things I expect to be in this module are stuff like Mockito, which I only use for testing. Please correct me if I'm wrong about this assumption.
When I open up my moduleB (by adding the word 'open' before the moduledecleration), the test runs smoothly. But obviously this is not what I want.
So my question really is: can I open up to the unnamed module so that my tests can run, but my module stays closed for anything other than the test?
Here's a simplified overview of the directory structure.
- parent
|
-> - pom.xml
- moduleA
- moduleB
|
-> - pom.xml
- src
|
-> - main
|
-> - java
|
-> - module.info
- com.example.service
|
-> - ModuleBService.java
- test
|
-> - java
|
-> - com.example
|
-> - Application.java
- com.example.service
|
-> - ModuleBServiceTest.java
As it turns out, the location of the Application.class is relevant. The module I am trying to test does not have a class annotated with #SpringbootApplication, because it's just a library. To test it's functionality, I have to start a SpringbootApplication in test. When the Application.java is in the same package as the ModuleBServiceTest.java, all is well. When I move it out in another package the error-message from above occurs. Why is that?

What you can do is to configure the surefire plugin to open the module to the unnamed modules in the POM of your moduleB
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
<!-- Allow access to the tests during test time -->
--add-opens moduleB/com.example.service=ALL-UNNAMED
<!-- Add export to test-util classes to moduleC if it wants to reuse these -->
--add-exports moduleB/com.example.service.test.util=moduleC
<!-- Prevent any illegal access to modules -->
--illegal-access=deny
</argLine>
</configuration>
</plugin>
</plugins>
</build>
I've also added a sample where you can explicitly export some test utility classes to a further module in case it wants to access these
As it turns out, the location of the Application.class is relevant. The module I am trying to test does not have a class annotated with #SpringbootApplication, because it's just a library. To test it's functionality, I have to start a SpringbootApplication in test. When the Application.java is in the same package as the ModuleBServiceTest.java, all is well. When I move it out in another package the error-message from above occurs. Why is that?
AFAIK Spring Boot will scan its package and any sub-packages for components, services and the like and will add these automatically to its configuration. If the application is not directly in an ancestor path it might not be able to find your test class, though the information given is a bit limited to be honest.

Related

Add class files to maven as a dependency [duplicate]

I have two modules, A and B, they are under the same parent. Now A is requiring for B as dependency. I can't just use jar as dependency type because module B is using spring-boot-maven-plugin, so I was wondering how can I set A's pom configuration to make A depend on B's compiled classes not jar?
- root
- A
- src # module A's source code
- target
- classes # module A's compiled classes
- A.jar # module A's compiled jar output
- pom.xml # module A's mvn config
- B
- src # module B's source code
- target
- classes # module B's compiled classes, HOW CAN I IMPORT THESE TO A?
- B.jar # module B's mvn config
- pom.xml # module B's mvn config
- pom.xml # parent mvn config
parent mvn config
...
<modules>
<module>A</module>
<module>B</module>
</modules>
...
module A mvn config
...
<parent>
<!- pointed to parent ->
</parent>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>B</artifactId>
<scope>??????????????</scope> # WHAT SHOULD I PUT HERE?
<type>???????????????</type> # WHAT SHOULD I PUT HERE?
</dependency>
<dependencies>
...
First of all: When A depends on the classes of some other module, it necessarily depends on the jar. You cannot depend on parts of a module or just the classes.
So let me sketch a solution:
If B is of <packaging>jar</packaging> (standard, also true if no packaging is given), then you can just use it as dependency. You do not need a scope or type entry.
If B is of some other packaging (including spring-defined packaging types, which I am no expert of), then you should not define a dependency from A on B. Instead, you define a third module C, which includes the classes that are used from A and from B and let both of them have a dependency on C.
Don't try to construct dependencies to non-jars. If you need classes, define a module with these classes and use it when the classes are needed.
Here is good information about maven dependency scope and type.
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
This should work fine for you. (Not tested)
<scope>compile</scope>
<type>jar</type>

Java how to use methods from another module in Intellij

I have added two projects as modules in empty intellij project.
Then I added in pom of module B following dependency to first project(module A):
<dependency>
<groupId>Tests</groupId>
<artifactId>Group</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
This allows me to import classes from module A into module B.
But I can't see any method from that module (it looks like classes are empty or they have only private fields/methods).
What am I missing? What should I do to see all public methods/fields from A module?
Thanks
Kamil
If you are adding one of them as a dependency, you can avoid to join them as modules. For local purposes, you can build(mvn clean package) one of them and add that as a dependency to another one. You can check relevant .class file to see the access levels of the class members.
For multi-module projects, please, see: https://www.jetbrains.com/help/idea/creating-and-managing-modules.html

How to get access to javax.annotation.Resource at run time in Java 9

I have a test:
public class ResourceTest {
#Test
public void test() throws ClassNotFoundException {
Class.forName("javax.annotation.Resource");
}
}
It tries to access javax.annotation.Resource. In java 8 it worked, but in java 9 (I'm using Oracle JDK 9) it fails with ClassNotFoundException.
As explained here Spring: #Resource injection stopped working under JDK9 , javax.annotation.Resource from the JDK is not available by default in Java 9.
I'm trying to get access to it using module descriptor:
module test {
requires java.xml.ws.annotation;
requires junit;
}
Here, I specifically request access to java.xml.ws.annotation module (which contains javax.annotation.Resource). But the test still fails.
When I remove that requires clause and add a dependency (as a library) which contains javax.annotations.Resource, it works:
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.1</version>
</dependency>
When I add them both (Maven dependency in pom.xml and requires java.xml.ws.annotation), compilation in IDEA fails with the following message:
the unnamed module reads package javax.annotation from both java.xml.ws.annotation and java.annotation
But Maven build still succeeds!
If I add java.xml.ws.annotation module via command line, it works (with no Maven dependency and with requires clause):
mvn clean test -DargLine="--add-modules java.xml.ws.annotation"
Do I do something wrong with my module description? How can I get access to JDK-supplied javax.annotation.Resource without command line switches?
The test project is available at https://github.com/rpuch/test-resource-jdk9
Just to clear out some confusion here. The ways to work stated in the question by you are alternatives and should not be combined as you have already seen.
the unnamed module reads package javax.annotation from both
java.xml.ws.annotation and java.annotation
So the way it would work is either:
You can use the compiler args to add modules
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<release>9</release>
<compilerArgs>
<arg>--add-modules</arg>
<arg>java.xml.ws.annotation</arg>
</compilerArgs>
</configuration>
</plugin>
OR
Make use of the javax.xml.ws.annotation being an upgradeable module which is when you can make use of the dependency
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.1</version>
</dependency>
Ideally this would be a preferrable option to stick to as the former is just an alternate to use the #Deprecated module marked forRemoval.
So the required clause by itself it not enough to get access to a
module... is this true for all JDK-supplied modules (excluding
java.base), or it is only true for deprecated modules?
No, the requires is just a part of declaration. [Think about this, prior to JDK 9 if you used a statement import some.foo.bar; in your class which was not added as a library(classpath) would that have worked?]. The module marked as required has to be on the modulepath for you to access it.
Update - The first option would not be supported any time longer with the use of JDK/11 or above wherein the JEP to Remove the Java EE and CORBA Modules is targetted.
For gradle build, adding the following to build.gradle works:
compile 'javax.annotation:jsr250-api:1.0'
tasks.withType(AbstractCompile) {
options.compilerArgs += ["--add-modules", "java.xml.bind"]
}
tasks.withType(Test) {
jvmArgs += ["--add-modules", "java.xml.bind"]
}

<Maven>How to add class files as dependency (not jar) in maven project?

I have two modules, A and B, they are under the same parent. Now A is requiring for B as dependency. I can't just use jar as dependency type because module B is using spring-boot-maven-plugin, so I was wondering how can I set A's pom configuration to make A depend on B's compiled classes not jar?
- root
- A
- src # module A's source code
- target
- classes # module A's compiled classes
- A.jar # module A's compiled jar output
- pom.xml # module A's mvn config
- B
- src # module B's source code
- target
- classes # module B's compiled classes, HOW CAN I IMPORT THESE TO A?
- B.jar # module B's mvn config
- pom.xml # module B's mvn config
- pom.xml # parent mvn config
parent mvn config
...
<modules>
<module>A</module>
<module>B</module>
</modules>
...
module A mvn config
...
<parent>
<!- pointed to parent ->
</parent>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>B</artifactId>
<scope>??????????????</scope> # WHAT SHOULD I PUT HERE?
<type>???????????????</type> # WHAT SHOULD I PUT HERE?
</dependency>
<dependencies>
...
First of all: When A depends on the classes of some other module, it necessarily depends on the jar. You cannot depend on parts of a module or just the classes.
So let me sketch a solution:
If B is of <packaging>jar</packaging> (standard, also true if no packaging is given), then you can just use it as dependency. You do not need a scope or type entry.
If B is of some other packaging (including spring-defined packaging types, which I am no expert of), then you should not define a dependency from A on B. Instead, you define a third module C, which includes the classes that are used from A and from B and let both of them have a dependency on C.
Don't try to construct dependencies to non-jars. If you need classes, define a module with these classes and use it when the classes are needed.
Here is good information about maven dependency scope and type.
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
This should work fine for you. (Not tested)
<scope>compile</scope>
<type>jar</type>

Source code in SoapUI maven

How I can add my source code ( java code ) to project SoapUI running by maven? I wrote own assertion class and check response in this class. First i made dir ext and put there .jar file. Now I want do the same, but with source code.
By adding a jar in the \ext folder you made the compiled class available to SoapUI test runner.
Instead of that you could include your code as a maven module in your project and add it as dependency. Your Java code should be a maven project for this to work.
A common approach is to create a "modules" directory in your project's root and add your java code in a subdirectory there, let's call it "assertion_module":
<root>
| - soapui-project.xml
| - pom.xml
| - modules
| - assertion_module
| - src
| - pom.xml
The pom.xml in the folder should have the necessary properties set, like below (sample values):
<groupId>assertion_module</groupId>
<artifactId>assertion_module</artifactId>
<name>assertion_module</name>
<version>0.1</version>
In you master pom.xml, i.e. the one that you use to run the SoapUI tests declare your assertion module, adding the following:
<modules>
<module>modules/assertion_module</module>
</modules>
In the soapui plugin section of this pom add the necessary dependency section:
<plugin>
<groupId>com.smartbear.soapui</groupId>
<artifactId>soapui-maven-plugin</artifactId>
<version>5.1.2</version>
<dependencies>
<dependency>
<groupId>assertion_module</groupId>
<artifactId>assertion_module</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
...
</plugin>
Now when you run your tests, the assertion_module will be compiled and be available to SoapUI test runner.
With this you no longer need to add the compiled jar in the \ext folder, although you still need to have it in the <SoapUI_installtion_directory>\bin\ext.

Categories