I know that if I want to get a resource for use in my unit tests, I can do something like:
String configPath = Objects.requireNonNull(
TestResources.class
.getClassLoader()
.getResource("config.properties")).getPath();
We also have some resources that are in a path defined in an environment variable. For that case we have been doing something like:
String testDataPath = env.get("TEST_DATA")
String specificUseCase = Paths.get(testDataPath, "path", "to", "specific", "resource").toString();
In this case, I'm using a relative path from TEST_DATA. Is there a way to cut relative paths out of the picture completely?
CodePudding user response:
Do not call the getPath() method of URL. It does not return a valid file name. If the returned resource URL points to a file path containing characters that aren’t allowed in URLs, like spaces, they would be percent-escaped.
Regardless, while you could theoretically create your own URLClassLoader in order to call getResource, there is no point to doing so. getResource and getResourceAsStream are specifically intended to read data bundled with an application.
I don’t see anything wrong with your use of Paths.get as it is.
I am concerned that the structure of the TEST_DATA directory will change and break my code. Is that something I should worry about?
Yes, but using getResource will not change that. getResource would actually be worse, because it would just return null if the desired resource is not found. When you read from a Path, you will get an informative exception (like NoSuchFileException) instead of just a mysterious null.
For what it’s worth, Java recommends using system properties instead of environment variables for configuring an application. System properties have to be set explicitly, and won’t just be something “left over” in a user’s login initialization that they forgot about. From the documentation of System.getenv:
System properties and environment variables are both conceptually mappings between names and values. Both mechanisms can be used to pass user-defined information to a Java process. Environment variables have a more global effect, because they are visible to all descendants of the process which defines them, not just the immediate Java subprocess. They can have subtly different semantics, such as case insensitivity, on different operating systems. For these reasons, environment variables are more likely to have unintended side effects. It is best to use system properties where possible. Environment variables should be used when a global effect is desired, or when an external system interface requires an environment variable (such as PATH).
