Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot Test MalformedURLException: unknown protocol: classpath

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: classpathexception 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: classpathexception 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.

like image 241
Evgeni Dimitrov Avatar asked Oct 22 '18 18:10

Evgeni Dimitrov


2 Answers

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

like image 97
borino Avatar answered Nov 07 '22 03:11

borino


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.

like image 1
ahvargas Avatar answered Nov 07 '22 01:11

ahvargas