1

I'm trying to find a way to get the absolute path for the resources folder in my junit test.

My doubt is not get a file in the resources folder (I now how to do this) but get the path to the resources folder.

Per example, if my file in my resources folder have this structure:

/opt/project/view/api/target/classes/
/opt/project/view/api/target/classes/file_in_resources.txt

I would like to get the location /opt/project/view/api/target/classes/ without use something ugly like:

URL location = this.getClass().getResource("/file_in_resources.txt");
String path = location.getPath();
String rightPath = path.substring(0, path.lastIndexOf("/"));

The idea is have a method like this.getClass().getResourcesPath(), but this kind of method not exists.

How to do?

Dherik
  • 17,757
  • 11
  • 115
  • 164
  • 2
    The answer is, don’t do it at all. When you try to run your program from a .jar file, the resources will be inside the .jar file and will not be separate files at all. Whatever you’re trying to do, there is another, better way to do it, one which doesn’t require converting resource locations to file paths. – VGR May 27 '16 at 19:21
  • @VGR, that should be an answer – Jim Garrison May 27 '16 at 19:23
  • @VGR If it's just for use in unit-tests it's not a problem? – Tobb May 27 '16 at 19:25
  • @Tobb If the program is ever going to run from a .jar file, the unit tests need to be run against a .jar file. – VGR May 27 '16 at 19:28
  • What now? One does not usually run unit tests against jar files, the tests are not included. – Tobb May 27 '16 at 19:28
  • @VGR, the tested class receive as parameter an absolute path to find a file (that I would like to put in the resources folder). This file in the production environment stay in the home folder of the user, it is a kind of "key". I would like to maintain this dummy key in my resources folder and pass the path for the tested class. – Dherik May 27 '16 at 19:35
  • @Dherik then what are you asking? If all you need is the absolute path to a certain file, then you have already answered your own question. – Tobb May 27 '16 at 19:39
  • @Tobb, I'm trying to find a better way. My answer no resolve the case when I don't have a file in the root of my resources. Per example, Instead of `file_in_resources.txt` I have only `somefolder/file_in_resources.txt`, the `lastIndexOf` strategy not work anymore. – Dherik May 27 '16 at 19:41
  • Ok, so the file in used in the class you are testing could be at any depth inside the supplied path? – Tobb May 27 '16 at 19:45
  • And is the problem that your current code is ugly, or that it doesn't do what you want it to? – Tobb May 27 '16 at 19:46
  • https://stackoverflow.com/a/56327069/715269 – Gangnus May 27 '19 at 13:32

4 Answers4

1

There could be a long philosophical discussion about the pro´s and con´s, if one should "have this question". But if you bump into it too like me, than this could be a way to go, if you want to do it with a current Java style (assumption: you´re file_in_resources.txt resides inside the appropriate and Unittest standard folder src/test/resources):

private String readFileFromResourcesAsString(String fileName) throws IOException {
    Path filePath = Paths.get("./src/test/resources/yourCustomPathHere/" + fileName);
    return Files.lines(filePath).collect(Collectors.joining());        
}

If you really want to stick to the folder view/api/target/classes/, you could use that Paths.get-statement with a java.net.URI instead (like Chetan Jadhav CD already mentioned):

Paths.get(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI());

This solution makes use of the more recent Java-APIs around NIO.2 (see oracle tutorials here) like

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

and some Java 8 stream API part to read the Files content into a String (you could change this part as you like :) ).

The

Paths.get(".")

is key here - it gives you the current working directory transparently whatever OS (Windows, Linux, MacOS) you´re using.

If you´re a Spring-User, the whole thing is even more easy! See so answer here.

Community
  • 1
  • 1
jonashackt
  • 12,022
  • 5
  • 67
  • 124
  • It is a terrible answer. The Paths/files/absolutepath technics is very different to getClass/getResource. The answer is NOT about the question. – Gangnus May 20 '19 at 07:22
  • Sorry, but i don't get your intention here: This answer is far from lavishly thrown down, it tries to comprehensibly explain another - current Java style - solution. The question owner (besides accepting this as the best answer) only mentioned "a method like this.getClass().getResourcesPath()", but his code is far away from that - and there's simply not such a method. So providing a working solution doesn't seem so bad as an answer to me. And thus I also really don't get your downvote, this is just rude - sorry. – jonashackt Jun 13 '19 at 10:45
  • In Java there are several situations, for which operations for finding current dir or current resource dir, or current classloader dir or current plugin dir, or current dir in jar (repeat all above for jar) work differently. Any answer not exact about the theme, is useless. And obviously the question author wants the resource dir and you propose the current one. The fact that the author acknowledged your answer could mean he didn't see a better one. Or maybe, your spring reference worked. – Gangnus Jun 16 '19 at 22:22
0

If your test class is located within the same resources folder, you could try:

URL location = TestClass.class.getProtectionDomain().getCodeSource().getLocation();
String path = location.getPath();
String rightPath = path.substring(0, path.lastIndexOf("/"));

If the resources folder isn't the same, you could navigate to it based on its relative location taking the location of the Test Class (obtained using the code above) as a reference point.

String adjustedPath = rightPath+"/resources";
Chetan Jadhav CD
  • 1,116
  • 8
  • 14
  • The problem with this for me was, that class.getProtectionDomain().getCodeSource().getLocation() is just directing to c:/yourPathHere/yourprojectNameHere/target/classes – jonashackt Sep 13 '16 at 14:03
  • OP says in the first sentence of his issue description that he wants the *absolute path* of the resources folder. So the path on a Windows based machine would start from the root of the drive `C:/` in this case. The `rightPath` variable would point to the location where the TestClass is. However, we can modify this variable and adjust it knowing the relative location of the resources folder, for eg by truncating the `/target/classes` portion of it and appending `/resources` at the end of the truncated string. Does this solve your problem? – Chetan Jadhav CD Sep 13 '16 at 17:11
  • Another terrible answer. The Paths/files/absolutepath technics is very different to getClass/getResource. The answer is NOT about the question. – Gangnus May 20 '19 at 07:22
-1

If you are in the context of a unit test, then it is no problem referencing a file directly, as you know where it is and it is not going anywhere. You can get the file url, then use Path to navigate upwards in the folder structure until you have the correct folder.

final URL location = this.getClass().getResource("/file_in_resources.txt");
final Path path = Paths.get(location.getPath());
final String folder = path.getParent() //getParent().getParent()...
                          .toString();
Tobb
  • 11,850
  • 6
  • 52
  • 77