Java中静态类的Field.set()

时间:2017-07-10 21:17:14

标签: java android reflection

我正在尝试编写一些单元测试来断言正确的密码套件用于我的应用程序中不同版本的Android SDK。

为了模仿Build.VERSION.SDK_INT的结果,我试图使用Field.set()来电...

我有一个看起来像这样的实用工具方法(从https://stackoverflow.com/a/40303593/1226095拉出并链接到答案):

private static void mockSdkVersion(Field field, Object newValue) throws Exception {
    field.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, newValue);
}

然后我有几个测试利用这个:

 @Test
    public void testApprovedCipherListForApi16() throws Exception {
        // force SDK_INT to 16
        mockSdkVersion(Build.VERSION.class.getField("SDK_INT"), 16);
        // obtain the list of suites that should be returned for API 16
        ArrayList<String> approvedCipherSuites = ConnectionSpec.APPROVED_CIPHER_SUITES;
        // assert things...
    }

@Test
public void testApprovedCipherListForApi20() throws Exception {
    // force SDK_INT to 20
    mockSdkVersion(Build.VERSION.class.getField("SDK_INT"), 20);
    // obtain the list of suites that should be returned for API 20
    ArrayList<String> approvedCipherSuites = ConnectionSpec.APPROVED_CIPHER_SUITES;
    // assert things...
}

当我一次运行一个测试时,这是有效的,但是当我一次运行它们时(例如使用像Jenkins这样的CI设置)它似乎没有重置值(它保持在16),假设是因为这是静态的。

任何想法  a)我怎么能绕过这个?  b)我怎么能嘲笑这个?

2 个答案:

答案 0 :(得分:0)

每次测试方法调用后,您需要重置Build.VERSION。像这样:

private static final int DEFAULT_VERION = Build.VERSION.SDK_INT;

@After
public void after(){
    mockSdkVersion( Build.VERSION.class.getField("SDK_INT"), DEFAULT_VERION );
}

答案 1 :(得分:0)

我发现我可以通过简单地将@Config(sdk = Build.VERSION_CODES.XXX)注释添加到测试方法中来复制我正在寻找的行为(假设您使用的是RoboElectric

http://robolectric.org/configuring/