【发布时间】:2013-02-05 08:50:58
【问题描述】:
有什么方法可以使用任何 Mocking Framework 在 Android 中模拟静态函数。 Mockito 可以模拟类,但不足以模拟静态函数。
我们将不胜感激。
提前致谢
【问题讨论】:
-
当然,您首先应该考虑是否可以删除静态调用......恕我直言,解决这个问题比编写非静态代码更有效
-
那么你能告诉我哪个框架将指导我编写静态函数的模拟调用
有什么方法可以使用任何 Mocking Framework 在 Android 中模拟静态函数。 Mockito 可以模拟类,但不足以模拟静态函数。
我们将不胜感激。
提前致谢
【问题讨论】:
模拟通过使用面向对象、继承等概念来工作......
基本上是通过覆盖看起来像真实对象的对象/实例中的某些方法和行为,因为它们是这些真实对象的子类。
换句话说,模拟部分来自于覆盖实例的方法。
无法覆盖静态方法 (afaik)。
因此,模拟静态调用并不容易(如果可能的话)。
事实证明,我上面的说法是错误的,这是不可能的。
我应该在这个网站上搜索重复的问题。请参阅下面的一些链接到声称在某些情况下为您执行此操作的框架。由于它们使用字节码,我不确定它们能否在 Android (ymmv) 上正常工作。
(感谢 Rohit 强迫我重新评估自己的信念)
【讨论】:
请试试这个:https://bintray.com/linkedin/maven/dexmaker-mockito-inline-extended
它帮助我成功地模拟了 Android Instrumented Tests 中的静态方法,但请注意,此功能需要在具有至少 Android P 的设备上运行。
这是我所做的:
将androidTestImplementation 'org.mockito:mockito-android:2.28.0' 替换为androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito-inline-extended:2.28.0'
然后像这样模拟静态方法:
static class StaticTrojan {
static String staticOpen() { return "horse"; }
}
@Test
public void testStubbingStaticMethod() {
MockitoSession session = mockitoSession().spyStatic(StaticTrojan.class).startMocking();
try {
when(StaticTrojan.staticOpen()).thenReturn("soldiers");
assertEquals("soldiers", StaticTrojan.staticOpen());
} finally {
session.finishMocking();
}
// Once the session is finished, all stubbings are reset
assertEquals("horse", StaticTrojan.staticOpen());
}
【讨论】:
如果您使用 Kotlin,那么要模拟静态函数,您可以连接 mockk 库项目:
androidTestImplementation "io.mockk:mockk-android:1.12.0"
如果您的测试位于应用程序模块中,则需要将AndroidManifest.xml 添加到 androidTest 目录。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="you.application.package">
<application
android:debuggable="true"
android:extractNativeLibs="true" />
</manifest>
然后您可以使用以下代码模拟静态函数:
import io.mockk.every
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import org.junit.Assert.assertEquals
import org.junit.Test
class TestMockingStaticFunction {
object StaticTrojan {
@JvmStatic
fun staticOpen(): String {
return "horse"
}
}
@Test
fun testMockingStaticFunction() {
assertEquals("horse", StaticTrojan.staticOpen())
mockkStatic(StaticTrojan::staticOpen)
val mockScope = every { StaticTrojan.staticOpen() } returns "solders"
assertEquals("solders", StaticTrojan.staticOpen())
unmockkStatic(StaticTrojan::staticOpen)
assertEquals("horse", StaticTrojan.staticOpen())
}
}
库 API 允许您轻松地模拟 Kotlin 对象,在上面的示例中,该对象仅用于使用 @JvmStatic 注释创建静态函数。
注意!此方法使用 Android P 从 API 级别 28 开始提供的JVMTI。您的应用程序可以使用较小的 API 编写,但您必须仅在 Android P 设备或更新版本的设备上运行的测试。
【讨论】: