如何在类路径上模拟属性文件的存在?

时间:2015-09-28 14:59:49

标签: java unit-testing junit properties mocking

这肯定是一个常见的问题。我有一个属性文件,如my-settings.properties,由应用程序类读取。当我编写测试类时,它需要测试my-settings.properties中可能存在的事物的不同场景,以确保最大的代码覆盖率(例如,空属性文件,基本属性文件等)。但我的my-settings.properties只能有一个src/test/resources

如果只有一些注释

,那真的很棒

@MockFileOnClassPath(use = "my-settings-basic.properties", insteadOf = "my-settings.properties")

然后我可以在my-settings-XXX.properties中拥有多个/src/test/resources文件,并在每个测试方法上注释正确的文件。但我找不到这样的东西。我使用的是JUnit 4.12。

我可以想到几个粗糙的解决方案:

  1. 在每次测试之前,找到文件系统上的文件,使用文件系统I / O复制它,然后在测试后再次删除它。但这很笨拙并且涉及很多冗余。更不用说我甚至不确定类路径目录是否可写。
  2. 使用模拟框架来模拟getResource。不知道我怎么会这样做,特别是因为有一百万种不同的方式来获取文件(this.getClass().getResourceAsStream(...)MyClass.class.getResourceAsStream(...)ClassLoader.getSystemClassLoader().getResourceAsStream(...)等。)
  3. 我认为这一定是一个常见的问题,也许在JUnit,Mockito,PowerMock,EasyMock或类似的东西中已有解决方案?

    编辑:有人指出此问题与Specifying a custom log4j.properties file for all of JUnit tests run from Eclipse重复,但并非如此。那个问题是想要在主调用和测试调用之间有一个不同的属性文件。对我来说,我希望在测试调用和另一个测试调用之间有一个不同的属性文件。

2 个答案:

答案 0 :(得分:2)

我发现每当处理文件时,最好引入Resource的概念。

例如:

public interface Resource {
    String getName();
    InputStream getStream();
}

然后你可以通过依赖注入传递资源:

public class MyService {
    private final Properties properties;

    public class MyService(Resource propFile) {
        this.properties = new Properties();
        this.properties.load(propFile.getStream());
    }

    ...
}

然后,在您的生产代码中,您可以使用ClasspathResourceFileResourceURLResource等,但在测试中,您可以使用StringResource等。

注意,如果你使用spring,你已经有了这个概念的实现。更多详情here

答案 1 :(得分:2)

您可以更改Service课程以接受resource文件的名称,然后使用name加载resource

public class MyService {

 public MyService(String resourceFileName){
   //and load it into Properties  getResourceAsStream(resourceFileName);
 }
}