Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/203.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中静态类上的Field.set()_Java_Android_Reflection - Fatal编程技术网

Java中静态类上的Field.set()

Java中静态类上的Field.set(),java,android,reflection,Java,Android,Reflection,我正在尝试编写一些单元测试,以断言在我的应用程序中,不同版本的Android SDK都使用了适当的密码套件 为了模拟Build.VERSION.SDK_INT的结果,我尝试使用Field.set调用 我有一个实用方法,它看起来像是从链接的答案中提取出来的: private static void mockSdkVersion(Field field, Object newValue) throws Exception { field.setAccessible(true); Fi

我正在尝试编写一些单元测试,以断言在我的应用程序中,不同版本的Android SDK都使用了适当的密码套件

为了模拟Build.VERSION.SDK_INT的结果,我尝试使用Field.set调用

我有一个实用方法,它看起来像是从链接的答案中提取出来的:

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我怎样才能模拟这个呢?

每次测试方法调用后,您都需要重置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 );
}

我发现我可以通过简单地向测试方法添加@Configsdk=Build.VERSION\u CODES.XXX注释来复制我想要的行为,假设您使用的是RoboElectric


为什么这些话现在进入我的脑海?我知道。。。但是这个代码库非常不稳定。。。努力解决这个问题……此外,我正在调用的是一个静态类,我觉得我会遇到同样的问题,无法模拟PowerMock还不是一个选项……就个人而言,我会试图避免单元测试静态类,因为你显然想摆脱它们。如果可能的话,我会尝试看一看端到端的集成测试,这将为您的重构工作提供更有价值的支持。。。然而,我对集成测试知之甚少,我仍在学习单元测试的who/what/where/when/why/how。。。我们有自上而下的授权和合并检查,包括所有新代码的单元测试。。。而这个故事-为了更新安卓“O”的密码套件-只编辑静态类…不会在所有测试之后运行一次??啊,不,它会在每个测试之后运行。。。但不幸的是,我没有看到变化。