Reputation: 4745
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
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
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
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