我正在使用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
}

当我go 测试它时,我会假设它总是可以工作的,并且希望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))
    }
}

I've also tried mocking MockableClass.Companion::class.java with no luck.

有人知道我需要做什么才能模拟这个getInstance功能吗?

推荐答案

我最后做的事...

Instead of mocking the static method I ended up using PowerMockito's whenNew function to return a mocked instance of MockableClass. The final code looks something like this:

@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))
    }
}

Kotlin相关问答推荐

来自SnapshotFlow的单元测试StateFlow仅发出initialValue

使用数据存储首选项Kotlin Jetpack Compose

为什么不';Kotlin是否在数据类构造函数中隐式分配null值可为null的字段?

创建包含 3 个相同项目的列表/使用返回类型重复

为什么 Kotlin main 函数需要 @JVMStatic 注解?

Kotlin .如何用从 1 到 90 的 5 个唯一数字填充列表中的每一行?

使用启动或使用 coroutineScope 启动协程之间的区别

Jetpack Compose:当状态从另一个活动改变时强制重组

Jetpack Compose - 单击 LazyColumn 的项目时应用程序崩溃

Kotlin 协程中的 Dispatchers.Main 和 Dispatchers.Default 有什么区别?

Kotlin通过映射委托属性,如果映射中不存在,则抛出NoTouchElementException

Android插件2.2.0-alpha1无法使用Kotlin编译

Kotlin 的 Double.toInt() 中使用了哪种方法,舍入还是截断?

TypeConverter()在Android的TypeConverter错误中具有私有访问权限

Java Integer.MAX_VALUE 与 Kotlin Int.MAX_VALUE

通过在 kotlin-gradle 中使用子项目Unresolved reference: implementation

Kotlin中的函数接口

你如何在 Kotlin 中注释 Pair 参数?

如何修复未解析的参考生命周期范围?

是否可以在不使用class的情况下将 Mockito 与 Kotlin 一起使用?