1

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();
    }
Community
  • 1
  • 1
workerjoe
  • 2,421
  • 1
  • 26
  • 49
  • 1
    Look at these question https://stackoverflow.com/questions/28673651/how-to-get-the-path-of-src-test-resources-directory-in-junit. – Dmitriy Popov Jun 27 '19 at 15:17
  • 1
    in that directory layout you need to use `src/resources/data.txt` as filename. – Ivan Jun 27 '19 at 15:31
  • @Ivan that didnt work but `src/main/resources/data.txt` worked. Frankly, I don't understand why. – workerjoe Jun 27 '19 at 15:58
  • You shouldn't access it as a file, but using `getClass().getResourceAsStream("/data.txt")` – Mark Rotteveel Jun 27 '19 at 16:03
  • @MarkRotteveel that's probably a best practice, but being new to Java I literally wanted to test whether I knew how to write code that would allow it to ingest a file. I already have working tests with mock data. – workerjoe Jun 27 '19 at 17:01
  • 1
    Resources aren't necessarily available as files on the filesystem (eg when packaged in a jar). If you want to use a file, by all means do that, but then you shouldn't define it as a resource. And you should either use an absolute path or the correct relative path (the path needs to be relative to the current working directory, which - when run from an IDE - is usually the root of your project). – Mark Rotteveel Jun 28 '19 at 06:20

0 Answers0