Unit test with resources loaded with ClassLoader and Maven Surefire - java

I have a JavaFX project that loads the FXML files using getClassLoader().getResource, for example:
Main.class.getClassLoader().getResource("fxml/App.fxml").
The main code runs fine but when I run tests with Maven Surefire Plugin I have this error:
java.lang.IllegalStateException: Location is not set.
javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2459)
javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
Upon further investigation I discovered that when getClassLoader().getResource() is called while executing the test, the path it tries to resolve is in "target/test-classes" folder, whereas the resources reside in "target/classes" folder. How do I solve this problem?
My project follows Maven's default structure if that is relevant.
Edit: added the line of code that does the resource loading

When running tests in Maven, the classpath is comprised of both target/classes and target/test-classes
target/classes is used to store compiled classes and resources (under src/main/java, src/main/resources)
target/test-classes is used to store compiled test classes and test resources (under src/test/java and src/test/resources respectively)
You don't show the code that doesgetClassLoader().getResource() and the most important is the parameter of this getResource - how does it get resolved in runtime (during the test), so its hard to say more, but probably the issue is that this parameter is not specified correctly.
For example, if its file src/main/resources/sample.xml it should be resolved as:
getClassLoader().getResource("/sample.xml")

Related

Disable test resource file compilation in Eclipse for Gradle project

My JUnit tests need Java source code files as input. I've created those files under src/test/resources. I read a test resource file from src/test/resources (e.g., src/test/resources/files/SimpleTestClass.java via
final String expectedClass = new String(ClassLoader.getSystemClassLoader()
.getResourceAsStream("files/SimpleTestClass.java")
.readAllBytes());
The behavior that I expect is that the test resource Java files will not be compiled. This is exactly what Gradle does, therefore, running the tests with gradle test works fine.
Unfortunately, running the JUnit tests from within Eclipse results in a compilation of those test resource Java files. The bin folder now includes .class files instead of the .java files.
I could exclude the test resource Java files from the compilation. However, this will also disable Eclipse's Java editor functionalities for those files, e.g., error highlighting or refactoring.
For the test resource Java source code files: How can I keep the Java editor functionalitites in Eclipse, but exclude the compilation of those files so that they still are copied to the bin folder?

Configuring JUnit Directory Structure in Maven

I have a Java Spring application with unit tests in the directory
src/test Specifically src/test/com/client/rest
I'd like to add a child directory here, something like
src/test/com/client/rest/controllers
Which contains the unit tests for all controllers of the application. I created a file in this directory with a "#Test" end-point, but did not do anything to POM.xml. When I run mvn clean package I get the following error
The goal you specified requires a project to execute but there is no POM in this directory [path]. Please verify you invoked Maven from the correct directory.
I tried adding this new directory as a testResource element under build in POM.xml, but that did not work. Prior to adding this new file, the tests ran fine with <testSourceDirectory>src/test</testSourceDirectory> under the build element.
How do I properly integrate this new JUnit directory into Maven?
EDIT: I moved my new file to the standard parent directory where the other JUnit test files are (src/test/com/client/rest) and it seemed to register fine. What is the best practice for storing JUnit class files, and is it worthwhile to try to create new child directories for organizational purposes?
I think the error comes from just running the mvn command from somewhere other than your project root.
How do I properly integrate this new JUnit directory into Maven?
Follow the Maven Standard Directory Layout - https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
Your tests should be under src/test/java/com/client/rest/controllers . They should then be discoverable and just work without any additional Maven configuration.
What is the best practice for storing JUnit class files, and is it worthwhile to try to create new child directories for organizational purposes?
It is worth organizing your tests. I think the piece you're missing is that you are writing tests in Java so you need to organize your tests with both directories and packages. So a test located under src/test/java/com/client/rest/controllers would have a package of com.client.rest.controllers .

JDK 9+ BuiltinClassLoader ModuleReference Resolution Will Use Class Path (not Jar) to Find Resources

I have run into a snag with the JPMS jdk.internal.loader.BuiltinClassLoader when executing main methods in the context of my IDE (I use IntelliJ 2018.1).
If a resource is loaded in an in module class using a standard method like
MyMainClass.class.getResourceAsStream("/some-resource")
The resource is not found because the ModuleReference is not a jar, but a class path, e.g.
[module org.ubl.scb, location=file:///home/christopher/IdeaProjects/systematik-catalogue-builder/web-anno/out/production/classes/]
All of the other entries in the nameToModule Map look like this:
key = "logback.core"
value = "[module logback.core, location=file:///home/christopher/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar]"
Of course, a resource will never be found in classes, but it could be if the location is the jar root.
Is this a bug or am I missing something?
This is an IDE related compiler output issue. The project uses a gradle build. The default output for a gradle build will create a directory structure like this:
build
-classes
-java
-main
module-info.class
-libs
-resources
However, to run tests or to execute main methods in a JPMS project, gradle does not work (yet). I use the built-in IntelliJ compiler which generates a completely different output structure than gradle. The default looks like this:
out
-production
-classes
-some/package/name
some-resource
module-info.class
One must rebuild a project using the Build Project (ctrl + F9) to generate this output structure if something changes. In this case, I suppose that the missing "some-resource" had not yet been copied into the IntelliJ output structure (probably because I had not rebuilt the project yet), so the BuiltinClassLoader would not find it there. It is perhaps confusing that resources are copied into a directory called "classes", (which is identical to the JAR), but that is how it is done.
The Gradle build output is not used at all by the IDE... This also has consequences for any compiler options like --add-modules that must be added to the IDE settings, even if they are specified in the gradle build script.
...

Where libraries' path are stored in intelliJ

I have several libraries in my intelliJ and one of them has junit jar. But project is not able to compiled because classes does not see the junit jar, although it is added under libraries.
I solved this problem by adding junit jar to another library and problem solved. But I want to know where is it specified (in which file) that in which library intelliJ is looking?
It depends on your project setup in Idea where they are being stored.
Either is the configuration located within the following folder structure:
.idea
Or within either of these files:
*.iml, *.ipr
^-- these files/folders is located under /path/to/your/project/<file/path>

How to access a XML file in a maven project so it stays available when packaged

I currently started working on a maven web-app project that needs to be launched with the jetty:run-exploded goal for development/debugging in eclipse.
Now, I have an XML file which contents I need to access at runtime. My problem is: where to put the file so that the code that does the reading works both in "exploded" and packaged (i.e. in the WAR) mode?
Putting the file in src/main/java (so as to be in the classpath) won't cut it since maven filters out all non-java files on packaging.
When the file is in src/main/resources, one mean would be to figure out the root path of the project (during eclipse development) and look into that directory - but this won't be the case anymore when the project will be packaged.
Of course I could go into writing code that tries to read the file from both locations, but this seems rather cumbersome. Any suggestions?
Files in src/main/resources are copied to the target/classes directory and are available on the class path. Just read them from the class path. As explained in How do I add resources to my JAR? from the maven documentation (with a test resource here):
In a unit test you could use a simple
snippet of code like the following to
access the resource required for
testing:
...
// Retrieve resource
InputStream is = getClass().getResourceAsStream("/test.properties" );
// Do something with the resource
...
In such case I put the file under src/main/resources directory and use Spring's ClassPathResource. This way the file is accessible in IDE, during Maven build process and in runtime.

Categories

Resources