Stub Value Of Build.version.sdk_int In Local Unit Test
I am wondering if there is anyway to stub the value of Build.Version.SDK_INT? Suppose I have the following lines in the ClassUnderTest: if (Build.VERSION.SDK_INT >= Build.VERSIO
Solution 1:
Change the value using reflection.
staticvoid 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
setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 123);
It is tested. Works.
Update: There is a cleaner way to do it.
Create an interface
interfaceBuildVersionProvider{
funcurrentVersion(): Int
}
Implement the interface
classBuildVersionProviderImpl : BuildVersionProvider {overridefuncurrentVersion() = Build.VERSION.SDK_INT
}
Inject this class as a constructor argument through the interface whenever you want current build version. Then in the tests when creating a SUT (System Under Test) object. You can implement the interface yourself. This way of doing things may be more code but follows the SOLID principles and gives you testable code without messing with reflection and system variables.
Solution 2:
As an alternative to reflection, you can use your own class that checks for API and then use Mockito to test the API-Dependent logic in fast JVM unit tests.
Example class
import android.os.Build
classSdkChecker{
fundeviceIsOreoOrAbove(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
}
Example tested method
funcreateNotificationChannel(notificationManager: NotificationManager) {
if (sdkChecker.deviceIsOreoOrAbove()) { // This sdkChecker will be mocked// If you target Android 8.0 (API level 26) you need a channel
notificationManager.createNotificationChannel()
}
}
Example unit tests
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.verify
import com.nhaarman.mockito_kotlin.verifyZeroInteractions
import com.nhaarman.mockito_kotlin.whenever
@TestfuncreateNotificationChannelOnOreoOrAbove() {
whenever(mockSdkChecker.deviceIsOreoOrAbove()).thenReturn(true)
testedClass.createNotificationChannel(mockNotificationManager)
verify(mockNotificationManager).createNotificationChannel()
}
@TestfuncreateNotificationChannelBelowOreo() {
whenever(mockSdkChecker.deviceIsOreoOrAbove()).thenReturn(false)
testedClass.createNotificationChannel(mockNotificationManager)
verifyZeroInteractions(mockNotificationManager)
}
Post a Comment for "Stub Value Of Build.version.sdk_int In Local Unit Test"