adamconkey
adamconkey

Reputation: 4745

getResourceAsStream() - InputStream null when using relative path

I am using Maven and running a JUnit test on a static method that tries to read in a file using:

InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);

And then using new InputStreamReader(is) to use as a reader in another call. This works when filename is just a filename (e.g. file.csv) but when filename is a relative path (e.g. src/test/resources/file.csv), is ends up being null.

I need it to handle relative paths, because I'm running a test suite via JUnit that looks for resources with relative paths and these tests are coming from a JAR that I have no control over changing (i.e. I implemented a facade implementation class that the test suite uses to call its own tests with its own resources - they are out of my control).

Is there a way for this approach to work with relative paths, or some other way that I can find those resources on my classpath that the tests are looking for?

Upvotes: 2

Views: 2373

Answers (3)

xerx593
xerx593

Reputation: 13261

Running tests in maven, src/test/resources/ is (by default) "mapped" to the root of the class(loader)path, so in your case /file.csv is the correct absolute path of src/test/resources/file.csv.

To load "src/test/resources/file.csv" (Resource) successfully (which is comple nonsense), you should have this file (physically) available: src/test/resources/src/test/resources/file.csv, or respectively src/main/java(which would also be mapped to cp root) .../src/test/resources/file.csv

Upvotes: 2

user908255
user908255

Reputation:

I have this on blog (in spanish)

http://lacuevadeyogui.blogspot.com/2015/04/diferencia-entre-uri-y-url.html

The problem in with the reference to file in src/test/resources

try this

URL url = getClass().getClassLoader().getResource("file.csv");
File f;
try {
    f = new File(url.toURI());
} catch (URISyntaxException e) {
    f = new File(url.getPath());
}

At the end, convert file to inputStream.

Upvotes: 0

tkroman
tkroman

Reputation: 4798

In your case is ends up being null because when a resource lookup is performed, the resources directory is entry point, so the complete path is expected to be test/resources/src/test/resources/file.csv or test/resources/src/test/resources/file.csv depending on how you run your tests.

The only reliable way you could achieve your goal is to take care about the correctness manually. Perhaps something like this:

static String getResourceFileName(String maybePath) {
    Path path = Paths.get(maybePath);
    if (path.getNameCount() > 0) {
        return path.getFileName().toString();
    } else {
        throw new IllegalArgumentException("Can't derive filename given " + maybePath);
    }
}

@Test
public void testSoq() throws Exception {
    String fileName0 = getResourceFileName("file");
    InputStream is0 = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName0);

    String fileName1 = getResourceFileName("src/test/resources/file");
    InputStream is1 = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName1);
    String string0 = new BufferedReader(new InputStreamReader(is0)).readLine();
    String string1 = new BufferedReader(new InputStreamReader(is1)).readLine();
    assertEquals(string0, string1); // OK
}

Maybe you'll have to write it according to the specifics of your case (account for possible nested diretories etc.), but I really think that given your inputs may be of arbitrary nature, this won't get much simpler.

Upvotes: 0

Related Questions