在kotlin中模拟伴侣对象功能

时间:2017-03-17 15:54:37

标签: 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函数?

1 个答案:

答案 0 :(得分:4)

我最终做了什么...

我最终使用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))
    }
}