Spring 启动测试 MalformedURLException:未知协议:类路径
Spring Boot Test MalformedURLException: unknown protocol: classpath
如果 java.net.URL
在 Spring 引导应用程序中使用,使用 classpath
协议,它会按预期工作,因为 Spring 引导寄存器 URLStreamHandlerFactory
。例如new URL("classpath: someFile.whatever")
.
但是当此代码作为 JUnit 测试执行时 java.net.MalformedURLException: unknown protocol: classpath
抛出异常。
当为 JUnit 测试初始化 Spring 上下文时,似乎没有注册适当的 URLStreamHandlerFactory
。
重现步骤:
1) 创建 Spring Boot Starter 项目(例如仅使用启动器 Web)。
2) 在src/main/resources
中添加test.json
文件
3) 添加以下 bean:
@Component
public class MyComponent {
public MyComponent() throws MalformedURLException {
URL testJson = new URL("classpath: test.json");
System.out.println(testJson);
}
}
4) 启动应用程序 java 应用程序工作正常
5) 运行 默认 "contextLoads" 测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringUrlTestApplicationTests {
@Test
public void contextLoads() {
}
}
java.net.MalformedURLException: unknown protocol: classpath
抛出异常
在 JUnit 测试中将 URL 与类路径资源一起使用的正确方法是什么?
在实际用例中,我无法更改 new URL("classpath: test.json")
,因为它来自第 3 方库。
试图在 src/test/resources
中复制 test.json
,以测试错误是否由缺少资源引起 - 没有成功。
我认为您可以尝试自动装配 ResourceLoader,并使用 resourceLoader.getResource("classpath:/test.json") 加载文件,它将从资源文件夹中加载文件。
我更喜欢以下使用 apache commons 的方式:
String url = IOUtils.toString(
this.getClass().getResourceAsStream("test.json"),"UTF-8"
);
URL testJson = new URL(url);
文件 test.json => 你可以保存在 src/test/resources 文件夹中 -> 它将从这里加载,maven 对我有用
这里有更多类似的方法
How to read a text-file resource into Java unit test?
最短和最简单的方法是在测试执行之前创建简单的方法,即为 'classpath' 协议创建和注册处理程序。
@BeforeClass
public static void init() {
org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.getInstance();
}
我刚刚检查过,它工作正常。这种方法也使用 spring-boot applications
内部
Spring 没有可以处理 "classpath:"
协议的 URL 的 URLStreamHandler
。 Spring 使用 ResourceLoader
API 处理此协议。加载资源后,您可以获得它的 URL。
但是,Java 提供了一种支持非标准协议的机制。我找到了一个 Whosebug 条目,应该可以回答您的问题。
Supporting Classpath URLs
问题是处理协议的 class 是 org.apache.catalina.webresources.TomcatURLStreamHandlerFactory
。你可以用这个修复你的测试:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MalformedUrlApplicationTests {
@Test
public void contextLoads() {
}
}
不过我觉得@borino 的回答更好
如果 java.net.URL
在 Spring 引导应用程序中使用,使用 classpath
协议,它会按预期工作,因为 Spring 引导寄存器 URLStreamHandlerFactory
。例如new URL("classpath: someFile.whatever")
.
但是当此代码作为 JUnit 测试执行时 java.net.MalformedURLException: unknown protocol: classpath
抛出异常。
当为 JUnit 测试初始化 Spring 上下文时,似乎没有注册适当的 URLStreamHandlerFactory
。
重现步骤:
1) 创建 Spring Boot Starter 项目(例如仅使用启动器 Web)。
2) 在src/main/resources
test.json
文件
3) 添加以下 bean:
@Component
public class MyComponent {
public MyComponent() throws MalformedURLException {
URL testJson = new URL("classpath: test.json");
System.out.println(testJson);
}
}
4) 启动应用程序 java 应用程序工作正常
5) 运行 默认 "contextLoads" 测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringUrlTestApplicationTests {
@Test
public void contextLoads() {
}
}
java.net.MalformedURLException: unknown protocol: classpath
抛出异常
在 JUnit 测试中将 URL 与类路径资源一起使用的正确方法是什么?
在实际用例中,我无法更改 new URL("classpath: test.json")
,因为它来自第 3 方库。
试图在 src/test/resources
中复制 test.json
,以测试错误是否由缺少资源引起 - 没有成功。
我认为您可以尝试自动装配 ResourceLoader,并使用 resourceLoader.getResource("classpath:/test.json") 加载文件,它将从资源文件夹中加载文件。
我更喜欢以下使用 apache commons 的方式:
String url = IOUtils.toString(
this.getClass().getResourceAsStream("test.json"),"UTF-8"
);
URL testJson = new URL(url);
文件 test.json => 你可以保存在 src/test/resources 文件夹中 -> 它将从这里加载,maven 对我有用
这里有更多类似的方法 How to read a text-file resource into Java unit test?
最短和最简单的方法是在测试执行之前创建简单的方法,即为 'classpath' 协议创建和注册处理程序。
@BeforeClass
public static void init() {
org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.getInstance();
}
我刚刚检查过,它工作正常。这种方法也使用 spring-boot applications
内部Spring 没有可以处理 "classpath:"
协议的 URL 的 URLStreamHandler
。 Spring 使用 ResourceLoader
API 处理此协议。加载资源后,您可以获得它的 URL。
但是,Java 提供了一种支持非标准协议的机制。我找到了一个 Whosebug 条目,应该可以回答您的问题。
Supporting Classpath URLs
问题是处理协议的 class 是 org.apache.catalina.webresources.TomcatURLStreamHandlerFactory
。你可以用这个修复你的测试:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MalformedUrlApplicationTests {
@Test
public void contextLoads() {
}
}
不过我觉得@borino 的回答更好