Java属性自动使用测试资源

时间:2016-03-17 16:30:27

标签: java classpath testng

我有一些类需要一些特定于环境的配置。我转向使用属性文件,这些文件在类的构造函数中加载。

public class MyClass {
    public MyClass() {
        try {
            ValidatedEnvironmentProperties props = new ValidatedEnvironmentProperties();
            props.load(MyClass.class.getResourceAsStream("/myclass.properties"));

ValidatedEnvironmentProperties延伸Properties。基本上,它使用Java System Property来设置密钥前缀。我将系统属性设置为production,在属性文件中,我有staging.url=...production.url=...。这允许我构建/运行时选择使用哪个配置而不需要更改属性文件名。

myclass.properties存储在src/main/resources

这很好用,我更喜欢它的工作原理。我的问题是我有点被TestNG困住了。我想在TestNG单元测试中测试一堆其他属性。这导致我创建了src/test/resources/myclass.properties。而不是"环境"键,我使用像bad_url_test.url=this_ain't_a_url这样的测试名称。

我认为src/test/resources会在classpath / classloader(术语?)中获得更高的优先级,从而导致加载特定于测试的属性。然后,对于我的各种测试,我只是将Java System属性设置为bad_url_test,实例化MyClass,测试我的断言,然后将System属性设置为新测试,实例化一个新对象,然后重复。

我认为问题的根源是MyClass的构造函数中的这一行:

props.load(MyClass.class.getResourceAsStream("/myclass.properties"));

MyClassTest中,我将这些内容用于尝试了解发生了什么:

    File f = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
    System.out.println("MyClass classpath: " + f.toString());
    f = new File(MyClassTest.class.getProtectionDomain().getCodeSource().getLocation().getPath());
    System.out.println("MyClassTest classpath: " + f.toString());

输出是:

MyClass classpath: /home/fandingo/code/project/build/classes/main
MyClassTest classpath: /home/fandingo/code/project/build/classes/test

MyClassTest是正确的,但我需要在MyClass的构造函数中可访问的内容,在运行测试时会自动更喜欢/src/test/resources/,而在正常运行时会/src/main/resources/

1 个答案:

答案 0 :(得分:1)

您需要inversion of control。即MyClass需要被告知从哪里获取其财产而不是自己决定。

有很多方法可以做到这一点,但它们都归结为相同的想法:MyClass在编译时不应该知道其属性来自何处。

e.g。

在MyClass.java中

ValidatedEnvironmentProperties props = new ValidatedEnvironmentProperties();
String resourceSupplierClassName = System.getProperty("resource-supplier-class-name",
        MyClass.class.getName());
Class<?> resourceSupplierClass = Class.forName(resourceSupplierClassName);
props.load(resourceSupplierClass.getResourceAsStream("/myclass.properties"));

在MyClassTest.java中

System.setProperty("resource-supplier-class-name", MyClassTest.class.getName());

同样,有很多方法可以做到这一点。您也可以使用dependency injection(一种控制反转形式)来代替传递系统属性等。您可以更改MyClass构造函数以将props作为参数,然后将责任放在MyClass的实例化器上以提供props,或者您可以使用依赖注入SpringGuice等框架,用于管理为main / test执行创建适当的props实例,并根据需要将其提供给需要它的对象。