如何在类路径上模拟属性文件的存在? [英] How can I mock the presence of a properties file on the classpath?
问题描述
这肯定是一个常见问题.我有一个类似my-settings.properties
的属性文件,该文件由应用程序类读取.当我编写测试类时,它需要测试my-settings.properties
中可能出现的各种情况,以确保最大的代码覆盖率(例如,空属性文件,基本属性文件等).但是我的src/test/resources
中只能有一个my-settings.properties
.
This surely is a common problem. I have a properties file like my-settings.properties
which is read by an application class. When I write a test class, it needs to test different scenarios of things that could be present in my-settings.properties
in order to ensure maximum code coverage (e.g. empty properties file, basic properties file etc). But I can only have one my-settings.properties
in my src/test/resources
.
如果只有一些注释,那将是非常好的
What would be really great is if there was just some annotation
@MockFileOnClassPath(use = "my-settings-basic.properties", insteadOf = "my-settings.properties")
然后,我可以在我的/src/test/resources
中仅包含多个my-settings-XXX.properties
文件,并在每种测试方法上标注正确的文件.但是我找不到这样的东西.我正在使用JUnit 4.12.
Then I could just have multiple my-settings-XXX.properties
files in my /src/test/resources
and just annotated the correct one on each test method. But I can't find anything like this. I'm using JUnit 4.12.
我可以想到几个粗略的解决方案:
I can think of a couple of crude solutions:
- 在每次测试之前,请在文件系统上找到文件,使用文件系统I/O复制该文件,然后在测试后再次将其删除.但这很笨拙,并且涉及很多冗余.更不用说我什至不确定classpath目录是否可写.
- 使用模拟框架模拟
getResource
.我什至不知道该怎么办,特别是因为有上百万种不同的方式来获取文件(this.getClass().getResourceAsStream(...)
,MyClass.class.getResourceAsStream(...)
,ClassLoader.getSystemClassLoader().getResourceAsStream(...)
等)
- Before each test, find the file on the file system, copy it using filesystem I/O, then delete it again after the test. But this is clumsy and involves a lot of redundancy. Not to mention I'm not even sure whether the classpath directory will be writable.
- Use a mocking framework to mock
getResource
. No idea how I would even do that, especially as there are a million different ways to get the file (this.getClass().getResourceAsStream(...)
,MyClass.class.getResourceAsStream(...)
,ClassLoader.getSystemClassLoader().getResourceAsStream(...)
etc.)
我只是认为这肯定是一个普遍的问题,也许在JUnit,Mockito,PowerMock,EasyMock或类似的东西中已经有解决方案了?
I just think this must be a common problem and maybe there is already a solution in JUnit, Mockito, PowerMock, EasyMock or something like that?
EDIT: Someone has specified that this question is a duplicate of Specifying a custom log4j.properties file for all of JUnit tests run from Eclipse but it isn't. That question is about wanting to have a different properties file between the main and test invocations. For me I want to have a different properties file between a test invocation and another test invocation.
推荐答案
我发现,每当处理文件时,最好引入Resource
的概念.
I find that whenever dealing with files, it's best to introduce the concept of a Resource
.
例如:
public interface Resource {
String getName();
InputStream getStream();
}
然后您可以通过依赖项注入来传递资源:
Then you can pass the resource in via dependency injection:
public class MyService {
private final Properties properties;
public class MyService(Resource propFile) {
this.properties = new Properties();
this.properties.load(propFile.getStream());
}
...
}
然后,在生产代码中,可以使用ClasspathResource
或FileResource
或URLResource
等,但是在测试中,可以使用StringResource
等.
Then, in your production code you can use a ClasspathResource
or maybe a FileResource
or URLResource
etc but in your tests you could have a StringResource
etc.
请注意,如果您使用spring,那么您已经对这个概念有所了解.更多详细信息此处
Note, if you use spring you already have an implenentation of this concept. More details here
这篇关于如何在类路径上模拟属性文件的存在?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!