I have a similar question to this guy who was trying to load a static file in IntelliJ but the difference is that I'm trying to load that static file from a test class and am unclear how to do it.
My project hierarchy in IntelliJ looks like this:
projectroot
.idea
src
main
java
net.joeclark.mypackage
MyClass.java
resources
data.txt
test
java
net.joeclark.mypackage
MyClassTest.java
I'm using IntelliJ IDEA Community 2019.1. I want to write a test in MyClassTest.java which calls on the data in the file data.txt
. The resources
directory is "marked" as the "Test Resources Root" and I am trying to open the file from MyClassTest.java like so:
@Test
void canDoSomethingWithTheFile() {
String fileName = "data.txt";
try(Stream<String> stream = Files.lines(Paths.get(fileName))) {
// do something with the file
} catch (IOException e) {
e.printStackTrace();
}
}
However, running the project in IntelliJ throws a NoSuchFileException.
I have tried variations on the filename like "/data.txt
" and "./data.txt
" and I have tried putting the file in a package directory structure under resources
, i.e. "resources/net/joeclark/mypackage
" and get the same issue.
Inspecting the target
directory I find that the static file has been deposited under classes
rather than test-classes
, as you see here:
target
classes
net.joeclark.mypackage
MyClass.class
data.txt
test-classes
net.joeclark.mypackage
MyClassTest.class
I don't know if that's the cause of my problem or not. How do I solve it? How can I open that static file in my test class?
Edit: not a duplicate question
The suggested duplicate is helpful, but (1) its accepted answer doesn't answer my question or its question (the highest-voted alternative is closer to the mark), and (2) it doesn't address either the "why" of what's happening, or the best practice to correct it.
What I would put in an answer, if allowed
I have discovered that the test seems to run with a working directory of "projectroot" for the source files, not the "target" or output directory, so if I use the path "src/main/resources/data.txt" I do reach the file. A better explanation of why that occurs would be helpful. (i.e., why does the compiled test class refer to the file in the source directories?).
I have also discovered that having resources
in the main
directory is less than a best practice, because that causes the test data file to be packaged with the .jar. By moving the resources
directory under test
I can run my test successfully (using "src/test/resources/data.txt") but the resource doesn't get packaged along with the compiled code.
Edit 2: A second way using ClassReader
Mark's comment suggested using getClass().getResourceAsStream("/data.txt")
. This produces an InputStream, but I didn't get any guidance on how to convert that into a Stream. Drawing on this answer I came up with the following, which works:
try(Stream<String> stream = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("/data.txt"))).lines()) {
// do the thing with the file;
} catch (NullPointerException e) { // note, not the same exception type
e.printStackTrace();
}