bjoernQ / unmock-plugin

Gradle plugin to be used in combination with the new unit testing feature of the Gradle Plugin / Android Studio to use real classes for e.g. SparseArray.
Apache License 2.0
323 stars 22 forks source link

Classes not mocked with Kotlin #58

Closed SpaceBison closed 5 years ago

SpaceBison commented 5 years ago

This might be related to #56. Using Unmock with Kotlin does not seem to work.

Example to reproduce:

Project level build.gradle buildscript block:

buildscript {
    ext.kotlin_version = '1.3.31'
    repositories {
        google()
        jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'de.mobilej.unmock:UnMockPlugin:0.7.3'
    }
}

Example test to reproduce:

class ExampleTest {

    @Test
    fun test() {
        assertTrue(Looper.getMainLooper().isCurrentThread)
    }
}

Result:

java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.

at android.os.Looper.getMainLooper(Looper.java)
at com.example.unmockkotlin.RegularTest.addition_isCorrect(RegularTest.kt:11)
bjoernQ commented 5 years ago

Hi,

by default only a small portion of the SDK is "unmocked". You could configure which classes you want but in this case Looper uses other classes e.g. MessageQueue which call into native code. This won't work.

You could:

Hope this helps.

Closing this because it works as designed

calvarez-ov commented 4 years ago

I came here looking for any info about mockk being used in conjuction with UnmockPlugin.

I only use mockk and was hoping to remove some of my mockk code by using UnmockPlugin instead, but I'm running into issues where mockk, which previously worked, is now broken. I don't have a sample project to share. I can provide more info if needed. But before getting too deep into this, I was wondering if there is already some known limitations making these two tools not work with each other.

For info, here's a small snippet:

val app = spyk(Application())
every { app.packageName } returns "some package"
every { app.applicationContext } returns app
assertEquals("some package", app.packageName)
// Pass this `app` instance to objects which will access `app.packageName` or `app.applicationContext`

When unmock is used, the every line fails with

io.mockk.MockKException: Missing calls inside every { ... } block.
    at io.mockk.impl.recording.states.StubbingState.checkMissingCalls(StubbingState.kt:14)
    at io.mockk.impl.recording.states.StubbingState.recordingDone(StubbingState.kt:8)
    at io.mockk.impl.recording.CommonCallRecorder.done(CommonCallRecorder.kt:47)
    at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:60)
    at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
    at io.mockk.MockKDsl.internalEvery(API.kt:92)
    at io.mockk.MockKKt.every(MockK.kt:104)
    at com.example.MyTest.setUp(MyTest.kt:66)

The error I get varies depending on:

I haven't found any combination which works

UPDATE: I migrated my module to use mockito instead of mockk, and it works.

bjoernQ commented 4 years ago

Thanks for the update! Good to hear Mockito solves the problem

I think I used the plug-in with mockk before but I should try it again to see if I can improve anything