11

My target is to mock Build.Version.SDK_INT with Mockito. Already tried:

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

Problem is that: when requires method after mock, and .SDK_INT is not a method.

IntoTheDeep
  • 4,027
  • 15
  • 39
  • 84
  • http://stackoverflow.com/questions/38074224/stub-value-of-build-version-sdk-int-in-local-unit-test – Nkosi Oct 28 '16 at 10:33
  • Perhaps don't..? It seems like you're trying to mock too hard. If you're trying to get code coverage for the line of code which reads that int, then why? If you're trying to get the system to show it behaves differently with different builds, then wrap the call to `Build` behind something you CAN mock. – Ashley Frieze Oct 28 '16 at 21:33

3 Answers3

20

So far from other questions similar to this one it looks like you have to use reflection.

Stub value of Build.VERSION.SDK_INT in Local Unit Test

How to mock a static final variable using JUnit, EasyMock or 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);
 }

...and then in this case use it like this...

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

Another way around would be to create a class that accesses/wraps the field in a method that can be later mocked

public interface BuildVersionAccessor {
    int getSDK_INT();
}

and then mocking that class/interface

BuildVersionAccessor buildVersion = mock(BuildVersionAccessor.class);
when(buildVersion.getSDK_INT()).thenReturn(16);
Community
  • 1
  • 1
Nkosi
  • 235,767
  • 35
  • 427
  • 472
7

This works for me while using PowerMockito.

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

Don't forget to type

@PrepareForTest({Build.VERSION.class})
hendrickpras
  • 71
  • 1
  • 2
0

In case of java.lang.ExceptionInInitializerError , use 'SuppressStaticInitializationFor' to suppress any static blocks in the class. Usable example as follows:

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

Be careful inner class must use $ instead of Dot .

Hemant Shori
  • 2,463
  • 1
  • 22
  • 20