【问题标题】:Mocking Static Functions in Android在 Android 中模拟静态函数
【发布时间】:2013-02-05 08:50:58
【问题描述】:

有什么方法可以使用任何 Mocking Framework 在 Android 中模拟静态函数。 Mockito 可以模拟类,但不足以模拟静态函数。

我们将不胜感激。

提前致谢

【问题讨论】:

  • 当然,您首先应该考虑是否可以删除静态调用......恕我直言,解决这个问题比编写非静态代码更有效
  • 那么你能告诉我哪个框架将指导我编写静态函数的模拟调用

标签: android mocking mockito


【解决方案1】:

模拟通过使用面向对象、继承等概念来工作......

基本上是通过覆盖看起来像真实对象的对象/实例中的某些方法和行为,因为它们是这些真实对象的子类。

换句话说,模拟部分来自于覆盖实例的方法。

无法覆盖静态方法 (afaik)。

因此,模拟静态调用并不容易(如果可能的话)。


编辑 - 我错了...

事实证明,我上面的说法是错误的,这是不可能的。

我应该在这个网站上搜索重复的问题。请参阅下面的一些链接到声称在某些情况下为您执行此操作的框架。由于它们使用字节码,我不确定它们能否在 Android (ymmv) 上正常工作。


(感谢 Rohit 强迫我重新评估自己的信念)

【讨论】:

  • 但是我可以使用 PowerMockito 和 Mockito 在 Java 项目中模拟静态函数。但我无法在 Android 项目中这样做。
  • 我加了dexmaker,mockito,在Android上可以正常运行。但是 PowerMockito 库似乎不能很好地工作。
【解决方案2】:

请试试这个: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());
    }
    

【讨论】:

    【解决方案3】:

    如果您使用 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 PAPI 级别 28 开始提供的JVMTI。您的应用程序可以使用较小的 API 编写,但您必须仅在 Android P 设备或更新版本的设备上运行的测试。

    【讨论】:

      猜你喜欢
      • 2020-03-26
      • 1970-01-01
      • 2014-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-09
      • 1970-01-01
      相关资源
      最近更新 更多