Spring Boot:如何在单元测试中从类路径中读取资源

33

我正在尝试在单元测试中从类路径读取文件,代码如下:

@Value("classpath:state.json")
Resource stateFile;

我有一个位于src/test/resources目录下的state.json文件。 当我尝试使用stateFile.getInputStream()读取此文件时,它没有返回任何内容。我做错了什么?

我的测试类如下所示:

@RunWith(SpringRunner.class)
@SpringBootTest

如果我尝试使用错误的文件,我可以看到代码会失败。因此,我认为它在类路径中看到了该文件,但由于某种原因没有读取其内容。

4个回答

19

我刚遇到了这个问题。我正在使用Maven。我查看了我的target/test-classes文件夹,我的资源文件不在那里(尽管它在我的src/test/resources文件夹中)。

我运行了mvn clean install,然后重新检查了我的target/test-classes文件夹,现在资源文件出现了。之后,我的测试可以找到该文件并且测试通过了。

因此,似乎在进行mvn clean之前不会复制您的资源文件。JUnit正在查找由maven构建的类路径,在文件实际进入target/test-classes文件夹之前,JUnit将无法找到它。


16

除非它是定义的属性,否则无法访问@Value资源。 应该是这样的。

@Value("${stateJsonPath}")
Resource stateFile;

如果您必须从硬编码的路径获取资源,则使用此方法。

Resource stateFile = new ClassPathResource("state.json");

3
这是哪个资源类?好像有5个。 - G_V
可能是 org.springframework.core.io.ClassPathResource - Conrad
3
这个答案是错误的。在@Value中强制使用“属性”(Spring环境的SpEL引用)是没有意义的。OP的代码@Value("classpath:state.json") Resource stateFile是完全有效的。 - Peter Wippermann

6

这应该很简单,注意路径以点号开头,表示当前目录;

@Test   
public void testFile() {
    String path = "./src/test/resources";
    String fileName = "test.zip";

    File file = new File(path, fileName);

    assertTrue(file.exists());
}

OP要求从classpath中读取文件,并想要使用Spring的依赖注入。 - Peter Wippermann
@PeterWippermann 对的,但是问题的标题与问题内容不一致。如果问题的标题不具体和清晰,那么SO将充满相同/类似标题但不同问题内容的重复问题。我的答案是读取文件到问题标题的一个例子。 - Levent Divilioglu
@PeterWippermann 对的,但是问题的标题与问题的内容不一致。如果问题的标题不具体和清晰,那么Stack Overflow上就会充斥着标题相同/类似但问题内容不同的重复问题。我的回答是一个关于读取文件的例子,与问题的标题相符。 - undefined
我以为我理解了你的意思,但标题明确提到了“Spring Boot:”!无论如何,如果标题与问题不匹配,我建议你编辑标题,这样未来的读者可以受益 :-) 我认为这也会减少重复的数量。 - Peter Wippermann

6

为后人分享解决方案。类路径中的文件可以使用org.springframework.core.io.ResourceLoader进行读取。例如,我有一个名为posts.json的示例数据文件,位于目录src/test/java/resources/data下,在测试用例执行期间作为@Before的一部分需要加载它。

@ActiveProfiles("test")
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SampleTest {

    @Autowired
    private ResourceLoader resourceLoader = null;

    @BeforeEach
    void init() {
        File dataFile = resourceLoader.getResource("classpath:data/posts.json").getFile();
        ...
        ...
    }

}

注意: 当你使用分类器classpath:时,文件应该存在于类路径中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接