How to deal with relative path in Junits between Maven and Intellij

I have a maven project with a module

/myProject
pom.xml
    /myModule
    pom.xml
       /foo
       bar.txt

Consider a Junit in myModule which needs to open bar.txt, with maven the basedir is the module directory.

So to open the file bar.txt :

  new File("foo/bar.txt")

This works well when you execute mvn test BUT when you launch the same junit in intellij, it fails because Intellij sets the basedir in the project directory, not the module directory.

Intellij tries to open myProject/foo/bar.txt instead of myProject/myModule/foo/bar.txt

Is there a way to deal with that ?


Solution 1:

Solution inspired by Guillaume :

In Run->Edit configuration->Defaults->JUnit->Working directory set the value $MODULE_DIR$ and Intellij will set the relative path in all junits just like Maven.

Solution 2:

If you want to keep your code, you can try to change the working directory in the run/debug configuration (first entry in the combo box giving access to what you want to run) Set this to your module root. But prefer the other suggested approach:

ClassLoader.getSystemResourceAsStream(youPath) 

Or my preferred:

getClass.getResource(youPath)

or

getClass.getResourceAsStream(youPath)

A leading '/' in path indicates the working dir of your project, while no '/' indicates a relative dir to current class.

I use this last solution for my tests: I put my test data resources at the same package level as the test source, or in a subdir to avoid too messy package.

This way I can do a simple call without complicated path and without having to deal with working directory:

project-root  
  - module A  
    - src  
      - test
        - rootfile.txt  
        - my-complicated-package-naming-root
          - mypackage
            - Test.java
            - testResource.xml  

I can get the files this way:

final URL rootfile= Test.class.getResource("/rootfile.txt");
final URL testResource= Test.class.getResource("testResource.xml");

Solution 3:

a) Don't use Files, use InputStreams. get your InputStream via

ClassLoader.getSystemResourceAsStream("foo/bar.xml")

Most APIs that deal with Files are happy with InputStreams as well.

b) Don't use foo directories, use directories both maven and your IDE know about (i.e. put them in src/main/resources or src/test/resources, so they are on the Class Path)

c) If you have an API that absolutely needs a File, not an InputStream, you can still do

new File(ClassLoader.getSystemResource("foo/bar.xml").toURI())

Solution 4:

You can specify the working directory for the test runner in the Run/Debug Configurations window:

enter image description here