10

I'm using JUnit 4, Java 8, and Gradle 1.12. I have a file with default json that I need to load. My project has src/main/java/ (containing the project source), src/main/resources/ (empty), src/test/java/ (unit test source), and src/test/resources/ (the json data file to load) directories. The build.gradle file is in the root.

In my code I have:

public class UnitTests extends JerseyTest
{
  @Test
  public void test1() throws IOException
  {
    String json = UnitTests.readResource("/testData.json");
    // Do stuff ...
  }

  // ...
  private static String readResource(String resource) throws IOException
  {
    // I had these three lines combined, but separated them to find the null.
    ClassLoader c = UnitTests.class.getClassLoader();
    URL r = c.getSystemResource(resource); // This is returning null. ????
    //URL r = c.getResource(resource); // This had the same issue.
    String fileName = r.getFile();
    try (BufferedReader reader = new BufferedReader(new FileReader(fileName)))
    {
      StringBuffer fileData = new StringBuffer();
      char[] buf = new char[1024];
      int readCount = 0;
      while ((readCount = reader.read(buf)) != -1)
      {
        String readData = String.valueOf(buf, 0, readCount);
        fileData.append(readData);
      }

      return fileData.toString();
    }
  }
}

From what I read, that should give me access to the resource file. However, I get a null pointer exception when I try to use the URL, because the getSystemResource() call returns null.

How do I access my resource files?

kwiqsilver
  • 1,017
  • 2
  • 11
  • 24

2 Answers2

16

Resource names don't start with a slash, so you'll need to get rid of that. The resource should preferably be read with UnitTests.getClassLoader().getResourceAsStream("the/resource/name"), or, if a File is required, new File(UnitTests.getClassLoader().getResource("the/resource/name").toURI()).

On Java 8, you could try something like:

URI uri = UnitTests.class.getClassLoader().getResource("the/resource/name").toURI();
String string = new String(Files.readAllBytes(Paths.get(uri)), Charset.forName("utf-8"));
Yuri G.
  • 4,323
  • 1
  • 17
  • 32
Peter Niederwieser
  • 121,412
  • 21
  • 324
  • 259
  • The issue was the slash. All of the examples I read had a leading slash for some reason. The Java 8 suggestion has some bugs. Here's the correct code, for anyone using this: `URI uri = UnitTests.class.getClassLoader().getResource(resource).toURI(); return new String(Files.readAllBytes(Paths.get(uri)), Charset.forName("utf-8"));` – kwiqsilver Jul 01 '14 at 19:21
  • 1
    Either the examples were using `Class#getResource` rather than `ClassLoader#getResource`, or they were wrong. Fixed the Java 8 code snippet. – Peter Niederwieser Jul 02 '14 at 05:41
0

I think you want getResource instead of getSystemResource. The latter is used to, for example, read a file from the file system, where the path would not be specified in terms of the jar.

You can also skip the class loader: UnitTests.class.getResource("...")

Docs about resources here

Edit: there are some more detailed comments in the answers here.

Community
  • 1
  • 1
Joshua Goldberg
  • 5,059
  • 2
  • 34
  • 39
  • I was using getResources, but it produces the same error. – kwiqsilver Jun 30 '14 at 23:51
  • After reading more carefully, I realize I misunderstood the getSystemResource docs. Its argument is specified in terms of the system environment's classpath, not the file system root, as I was thinking when I wrote the answer above. I'll leave the answer here for the sake of the links. – Joshua Goldberg Jul 01 '14 at 20:31