模拟/伪造静态最终属性

时间:2018-02-09 17:58:25

标签: java unit-testing jmockit

我有一个类RequireJavaVersion,我想编写测试,如下所示:

public void execute( EnforcerRuleHelper helper )
     throws EnforcerRuleException
 {
    String javaVersion = SystemUtils.JAVA_VERSION;
    Log log = helper.getLog();

    log.debug( "Detected Java String: '" + javaVersion + "'" );
    javaVersion = normalizeJDKVersion( javaVersion );

此外,我的课程SystemUtils如下所示:

public static final String JAVA_VERSION = getSystemProperty("java.version");

所以我想写一个这样的测试(使用JMockit):

@Rule
public ExpectedException exception = ExpectedException.none();

public static class FakeSystemUtils extends MockUp<SystemUtils> {
    private final String fakedVersion;
    public FakeSystemUtils(String version)
    {
        this.fakedVersion = version;
    }
    @Mock
    private final String getSystemProperty(final String property) {
      return this.fakedVersion;
  }    
};
..

new FakeSystemUtils( "1.4" );

rule = new RequireJavaVersion();
rule.setVersion( "1.5" );

exception.expect( EnforcerRuleException.class );
exception.expectMessage( "Detected JDK Version: 1.4 is not in the allowed range 1.5." );
rule.execute( helper );

所以现在的问题是,看起来SystemUtils类看起来似乎是一次初始化,之后就不再......而且进一步的测试都会失败......(或者我错了什么)。

所以我现在不确定我是否会走错方向。 Fake类只会伪造getProperty..method,但问题是:这是正确的方法还是我需要进入不同的方向并尝试伪造最终的静态属性?有人有想法或暗示吗?

1 个答案:

答案 0 :(得分:0)

在深入了解@tsolakp的细节和提示之后,我找到了一个解决方案:

现在我可以设置public static final String JAVA_VERSION的结果或多或少简单来检查其余的代码。

@RunWith( PowerMockRunner.class )
@PrepareForTest( { SystemUtils.class } )
public class RequireJavaVesionTest
{
   ...
    @Test
    public void first()
        throws EnforcerRuleException
    {
        Whitebox.setInternalState( SystemUtils.class, "JAVA_VERSION", "1.4" );

        rule = new RequireJavaVersion();
        rule.setVersion( "1.5" );

        exception.expect( EnforcerRuleException.class );
        exception.expectMessage( "Detected JDK Version: 1.4 is not in the allowed range 1.5." );
        rule.execute( helper );
    }

这也与JUnit规则结合使用。