与Mockito模拟构建版本

Int*_*eep 6 testing android mocking mockito android-testing

我的目标是用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);
Run Code Online (Sandbox Code Playgroud)

问题是:当mock需要方法时,而.SDK_INT不是方法.

Nko*_*osi 5

到目前为止,与其他类似问题相比,您似乎不得不使用反射。

本地单元测试中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);
 }
Run Code Online (Sandbox Code Playgroud)

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

setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 16);
Run Code Online (Sandbox Code Playgroud)

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

public interface BuildVersionAccessor {
    int getSDK_INT();
}
Run Code Online (Sandbox Code Playgroud)

然后模拟该类/接口

BuildVersionAccessor buildVersion = mock(BuildVersionAccessor.class);
when(buildVersion.getSDK_INT()).thenReturn(16);
Run Code Online (Sandbox Code Playgroud)

  • 这在我的代码中不再有效 - 我收到“java.lang.NoSuchFieldException:修饰符”,并且我的测试全部失败。 (3认同)

小智 5

这对我来说在使用PowerMockito时很有用.

Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", 16);
Run Code Online (Sandbox Code Playgroud)

不要忘记打字

@PrepareForTest({Build.VERSION.class})
Run Code Online (Sandbox Code Playgroud)