简体   繁体   English

通过系统属性的静态最终字段进行单元测试

[英]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 即使在测试之前在静态初始化程序中设置了系统属性,接口字段也将返回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. 我正在使用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. 对您来说是个坏消息:由于静态, MYFIELD字段在加载MyInterface进行评估。 So, if your test classes have static references to MyInterface , it is loaded at the same time than your test classes are. 因此,如果您的测试类具有对MyInterface静态引用,则它将与您的测试类同时加载。 So, you have no choice to set a System property by code prior to executing your tests. 因此,在执行测试之前,您别无选择通过代码设置System属性。

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 . 但是,如果您确实需要在接口的成员中存储一些常量值,则从Sytem属性中获取这些值是没有意义的:常量旨在精确地是常量

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: 相反,如果您拒绝重构代码,则可以“按原样”运行测试的唯一方法是在调用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... JVM加载类,然后设置系统属性,但是类已经加载,并且静态字段初始化为null,因为在类加载时属性为空...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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