If java.net.URL
is used in a Spring Boot application, with classpath
protocol, it works as expected, because Spring Boot registers URLStreamHandlerFactory
. e.g. new URL("classpath: someFile.whatever")
.
But when this code is executed as JUnit test java.net.MalformedURLException: unknown protocol: classpath
exception is thrown.
It seems that the appropriate URLStreamHandlerFactory
is not registered when the Spring context is initialized for a JUnit test.
Steps to reproduce:
1) Create Spring Boot Starter project (e.g. using only starter Web).
2) add test.json
file in src/main/resources
3) Add the following bean:
@Component
public class MyComponent {
public MyComponent() throws MalformedURLException {
URL testJson = new URL("classpath: test.json");
System.out.println(testJson);
}
}
4) Starting the app as java application works OK
5) Run the default "contextLoads" test:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringUrlTestApplicationTests {
@Test
public void contextLoads() {
}
}
java.net.MalformedURLException: unknown protocol: classpath
exception is thrown.
What is the appropriate way to use URL with classpath resources in JUnit test?
In the real use-case I cannot alter the new URL("classpath: test.json")
because it comes from 3th party library.
Tried to copy test.json
in src/test/resources
, to test if the error could be caused by a missing resource - no success.
the shortest and easiest way is to create simple method before test execution, which is creating and registering handlers for 'classpath' protocol.
@BeforeClass
public static void init() {
org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.getInstance();
}
I just checked and it works fine. This approach also using inside of spring-boot applications
The problem is that the class that is handling the protocol is org.apache.catalina.webresources.TomcatURLStreamHandlerFactory
. You can fix your test with this :
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MalformedUrlApplicationTests {
@Test
public void contextLoads() {
}
}
But i think @borino answer is better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With