unit-testing - 在 kotlin 中模拟同伴对象函数

标签 unit-testing kotlin powermock

我正在使用 PowerMock 和 Roboelectric,并希望模拟一个类的伴随对象函数。当我这样做时,我得到一个错误:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

我所拥有的基本上是这样的:

open class MockableClass private constructor(context: Context) {

    companion object {

        private val INSTANCE_LOCK = Any()
        private var sInstance: MockableClass? = null

        @JvmStatic
        fun getInstance(context: Context): MockableClass? {
            synchronized(INSTANCE_LOCK) {
                sInstance = (sInstance ?: MockableClass(context).let {
                    if (it.isValid) it
                    else null
                }
            }
            return sInstance
        }
    }

    init {
        // Do some initialization using context...
        // Set isValid to true/false depending on success
    }

    val isValid: Boolean
}

当我去测试它时,我会假设它总是可以工作,并希望 getInstance 只返回 MockableClass 的模拟版本。

@RunWith(RobolectricTestRunner::class)
@Config(manifest = "src/main/AndroidManifest.xml",
        constants = BuildConfig::class,
        sdk = intArrayOf(23))
@PowerMockIgnore("org.mockito.*", "org.robolectric.*", "android.*")
@PrepareForTest(MockableClass::class)
class MyTest {

    private lateinit var context: Context

    @get:Rule
    val rule = PowerMockRule()

    @Before
    fun setUp() {
        context = RuntimeEnvironment.application as Context
    }

    @Test
    fun test() {
        val instance = mock(MockableClass::class.java)
        mockStatic(MockableClass::class.java)
        `when`(MockableClass.getInstance(Matchers.isA(Context::class.java)))
                .thenReturn(instance)
        assertEquals(instance,
                MockableClass.getInstance(RuntimeEnvironment.application as Context))
    }
}

我也尝试过模拟 MockableClass.Companion::class.java,但没有成功。

有谁知道我需要做什么才能模拟出这个 getInstance 函数?

最佳答案

我最终做了什么......

我最终没有模拟静态方法,而是使用 PowerMockito 的 whenNew 函数返回 MockableClass 的模拟实例。最终代码如下所示:

@RunWith(RobolectricTestRunner::class)
@Config(manifest = "src/main/AndroidManifest.xml",
        constants = BuildConfig::class,
        sdk = intArrayOf(23))
@PowerMockIgnore("org.mockito.*", "org.robolectric.*", "android.*")
@PrepareForTest(MockableClass::class)
class MyTest {

    private lateinit var context: Context

    @JvmField
    @Rule
    var rule = PowerMockRule()

    @Before
    fun setUp() {
        context = RuntimeEnvironment.application as Context
    }

    @Test
    fun test() {
        val instance = mock(MockableClass::class.java)
        instance.isValid = true
        whenNew<MockableClass>("com.example.MockableClass")
                .withAnyArguments()
                .thenReturn(instance)
        assertEquals(instance, MockableClass.getInstance(context))
    }
}

关于unit-testing - 在 kotlin 中模拟同伴对象函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42861972/

相关文章:

unit-testing - 使用 DI 进行单元测试和模拟服务

java - 导入无法解决(Junit)

android - 如何从 Kotlin 中的 RequestBody 获取正文字符串?

java - 连接到 Axon 服务器时更改节点的实例名称

android - Gradle Copy 任务不复制文件

junit - 是否可以在不使用 powermock 的情况下在 Mockito 中模拟 UUID?

.net - 在项目开始很久之后才开始单元测试?

android - Espresso - 每次测试方法后 Activity 都会关闭。有没有办法我们不能停止关闭 Activity 和运行其他测试方法

kotlin - 获得改造异常方法返回类型不得在 kotlin 中包含类型变量或通配符

java - JUnit 类别不会运行某些测试