简体   繁体   中英

Unit testing with a static final field from system properties

I have an interface with a public static final field which is pulled from system properties. It looks like this:

public interface MyInterface {
    public static final String MYFIELD = System.getProperty("MyField");
    ...
}

I am writing a unit test which uses this field. Even when I set the system property in a static initialiser before the test, the interface field returns null

System.out.println(System.getProperty("MYField")); //returns "MyField"
System.out.println(MyInterface.MYFIELD); //returns null

Why is the interface field not set? What is the best way to handle this situation? I can't just set the field value in my test because it is final static.

UPDATE:

I may have missed out an important detail; I am using Mocktio. It looks something like this

public class MyTest {

    static {System.setProperty("MyField", "MyValue");}

    @Test
    public void test1() {
        try {
            final MyInterface mockInterface = Mockito.mock(MyInterface.class);
            ...
        }
     }
}

Bad news for you: Being static, the MYFIELD field is evaluated at the time of MyInterface being loaded. So, if your test classes have static references to MyInterface , it is loaded at the same time than your test classes are. So, you have no choice to set a System property by code prior to executing your tests.

I doubt your are using a good approach: Generally, an interface should represent a behaviour , not just a bunch of arbitrary constants. But, in case you actually need to store some constant values in an interface's members, it is nonsense to get those values from the Sytem properties: Constant are intended to be precisely constants .

If you need that your program depend on arbitary values, they should be received as input parameters (in constructors or methods), precisely to give you the chance to set them values to your willing when making tests. This refactoring would have a cost in developing time, but your code would become cleaner and safer.

Instead, if you refuse to refactor your code, the only way you could run your tests "as is" is to set the System property values when calling the JVM:

java -DMyField=... foo.bar.MyTest

Static fields initialized at class load time. JVM load class and then you set system property, but class already loaded and static fields initialized with null because at class load time properties is empty...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM