Unit testing kotlin中的伴对象函数模拟

Unit testing kotlin中的伴对象函数模拟,unit-testing,kotlin,powermock,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()).thenRetur

我正在使用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))
    }
}
@RunWith(RobolectrictTestRunner::class)
@Config(manifest=“src/main/AndroidManifest.xml”,
常量=BuildConfig::类,
sdk=intArrayOf(23))
@PowerMockIgnore(“org.mockito.*”、“org.roblectric.*”、“android.*”)
@PrepareForTest(MockableClass::class)
类MyTest{
私有lateinit变量上下文:上下文
@JvmField
@统治
var rule=PowerMockRule()
@以前
趣味设置(){
上下文=RuntimeEnvironment.application作为上下文
}
@试验
趣味测试(){
val instance=mock(MockableClass::class.java)
instance.isValid=true
whenNew(“com.example.MockableClass”)
.withAnyArguments()
.thenReturn(实例)
assertEquals(实例,MockableClass.getInstance(上下文))
}
}

我会删除Robolectric标签,因为这只是关于Kotlin和反射的问题。公平地说,我不确定类加载器是否与此有关。三天之后,这完全有帮助。谢谢