Evg*_*tin 9 android unit-testing mockito powermock
我想知道是否还有存根的价值Build.Version.SDK_INT?假设我在以下行中有以下几行ClassUnderTest:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
//do work
}else{
//do another work
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能涵盖所有代码?
我的意思是我想用不同的SDK_INT运行两个测试来输入两个块.
有可能在android 本地单元测试中使用Mockito/ PowerMockito?
谢谢
tos*_*inl 27
使用反射更改值.
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"), 123);
Run Code Online (Sandbox Code Playgroud)
经过测试.作品.
作为反射的替代方法,您可以使用您自己的类来检查API,然后使用Mockito在快速JVM单元测试中测试API依赖的逻辑。
示例类
import android.os.Build
class SdkChecker {
fun deviceIsOreoOrAbove(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
}
Run Code Online (Sandbox Code Playgroud)
示例测试方法
fun createNotificationChannel(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()
}
}
Run Code Online (Sandbox Code Playgroud)
示例单元测试
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.verify
import com.nhaarman.mockito_kotlin.verifyZeroInteractions
import com.nhaarman.mockito_kotlin.whenever
@Test
fun createNotificationChannelOnOreoOrAbove() {
whenever(mockSdkChecker.deviceIsOreoOrAbove()).thenReturn(true)
testedClass.createNotificationChannel(mockNotificationManager)
verify(mockNotificationManager).createNotificationChannel()
}
@Test
fun createNotificationChannelBelowOreo() {
whenever(mockSdkChecker.deviceIsOreoOrAbove()).thenReturn(false)
testedClass.createNotificationChannel(mockNotificationManager)
verifyZeroInteractions(mockNotificationManager)
}
Run Code Online (Sandbox Code Playgroud)
java 17的解决方案,2023 年。
简单步骤:
1.添加通用方法
private fun setStaticFieldViaReflection(field: Field, value: Any) {
field.isAccessible = true
getModifiersField().also {
it.isAccessible = true
it.set(field, field.modifiers and Modifier.FINAL.inv())
}
field.set(null, value)
}
private fun getModifiersField(): Field {
return try {
Field::class.java.getDeclaredField("modifiers")
} catch (e: NoSuchFieldException) {
try {
val getDeclaredFields0: Method =
Class::class.java.getDeclaredMethod(
"getDeclaredFields0",
Boolean::class.javaPrimitiveType
)
getDeclaredFields0.isAccessible = true
val fields = getDeclaredFields0.invoke(Field::class.java, false) as Array<Field>
for (field in fields) {
if ("modifiers" == field.name) {
return field
}
}
} catch (ex: ReflectiveOperationException) {
e.addSuppressed(ex)
}
throw e
}
}
Run Code Online (Sandbox Code Playgroud)
2.将这些标志添加到gradle(其他情况可以更改)
android {
...
testOptions {
unitTests.all {
jvmArgs(
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED"
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
3.使用示例
private val testSocManufacturer = "test-soc-manufacturer"
setStaticFieldViaReflection(
Build::class.java.getDeclaredField("SOC_MANUFACTURER"),
testSocManufacturer)
private val testSocModel = "test-soc-model"
setStaticFieldViaReflection(
Build::class.java.getDeclaredField("SOC_MODEL"),
testSocModel)
setStaticFieldViaReflection(
Build.VERSION::class.java.getDeclaredField("SDK_INT"),
30)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3475 次 |
| 最近记录: |