使用 Mockito 模拟构建版本

问题描述 投票:0回答:4

我的目标是用 Mockito 模拟 Build.Version.SDK_INT 。已经尝试过:

final Build.VERSION buildVersion = Mockito.mock(Build.VERSION.class);
doReturn(buildVersion.getClass()).when(buildVersion).getClass();
doReturn(16).when(buildVersion.SDK_INT);

问题是:当mock之后需要方法时,.SDK_INT不是一个方法。

android testing mocking mockito android-testing
4个回答
20
投票

到目前为止,从与此类似的其他问题来看,您似乎必须使用反射。

本地单元测试中Build.VERSION.SDK_INT的存根值

如何使用 JUnit、EasyMock 或 PowerMock 模拟静态最终变量

static void setFinalStatic(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);
 }

...然后在这种情况下像这样使用它...

setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 16);

另一种方法是创建一个类,该类在稍后可以模拟的方法中访问/包装该字段

public interface BuildVersionAccessor {
    int getSDK_INT();
}

然后嘲笑该类/接口

BuildVersionAccessor buildVersion = mock(BuildVersionAccessor.class);
when(buildVersion.getSDK_INT()).thenReturn(16);

7
投票

这对我在使用 PowerMockito 时有效。

Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", 16);

别忘了输入

@PrepareForTest({Build.VERSION.class})

0
投票

如果出现 java.lang.ExceptionInInitializerError ,请使用 'SuppressStaticInitializationFor' 抑制类中的任何静态块。可用示例如下:

@SuppressStaticInitializationFor({ "android.os.Build$VERSION", "SampleClassName" )}

注意内部类必须使用 $ 而不是 Dot 。


0
投票

您可以使用 Robolectric 配置 SDK 级别。

@RunWith(RobolectricTestRunner::class)
@Config(manifest= Config.NONE)
class RandomTest {
    @Config(sdk = [28])
    @Test
    fun test() {
        assertTrue(methodToTest())
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.