Maven测试本地正常,Bitbucket Pipeline中抛出空指针异常
核心差异:资源的存在形式不同
你在本地Eclipse或命令行运行正常,是因为Maven会把src/test/resources下的文件复制到本地文件系统的target/test-classes目录,这些资源是实实在在的物理文件。这时候用getResource().getFile()能拿到有效的文件路径,自然能找到文件。
但Bitbucket Pipeline是容器化环境,构建后的测试资源要么是在target/test-classes的目录结构中,但类加载器会把整个类路径作为一个整体加载;要么是被临时打包成了JAR。这时候getResource().getFile()返回的路径不是普通的文件路径(可能是jar:file:/xxx/ConfigTest.json这种格式),File类无法识别这种路径,甚至getResource()可能直接返回null,导致你看到的NullPointerException。
问题根源
你的代码依赖于资源是文件系统中的独立文件,但CI/CD容器环境中,类路径资源是嵌入到类路径的目录/JAR中的,不是独立的物理文件,所以用File对象访问必然失效。
通用解决方案:用输入流读取资源
不管是本地还是CI环境,用输入流读取类路径资源都是通用的正确方式,别再用File了。给你两种可行的写法:
写法1:用类加载器获取输入流
import java.io.InputStream; import org.junit.Assert; import org.junit.Test; public class ClassLoaderTest { @Test public final void test() { // 资源在src/test/resources根目录,路径不需要前导斜杠 try (InputStream configStream = this.getClass().getClassLoader().getResourceAsStream("ConfigTest.json")) { // 先验证资源是否存在 Assert.assertNotNull("ConfigTest.json 未在类路径中找到", configStream); // 这里可以添加读取流的逻辑,比如转成字符串或者解析JSON } catch (Exception e) { Assert.fail("加载ConfigTest.json失败:" + e.getMessage()); } } }
写法2:用当前类的getResourceAsStream
如果你的测试类和资源不在同一个包下,也可以用带前导斜杠的路径(表示从类路径根开始查找):
InputStream configStream = this.getClass().getResourceAsStream("/ConfigTest.json");
补充说明
你之前尝试的线程上下文类加载器,本质上和普通类加载器面临的问题一样——核心不是用哪个类加载器,而是不要用File来访问类路径资源。本地能运行只是因为资源是物理文件,但这种写法本身就不具备跨环境兼容性。
内容的提问来源于stack exchange,提问作者stwissel

