mockk / mockk

mocking library for Kotlin
https://mockk.io
Apache License 2.0
5.45k stars 346 forks source link

Bug: unexpected behavior when using spyk with `Intent` #326

Open davigonz opened 5 years ago

davigonz commented 5 years ago

Hi here, before starting with the explanation, I would like to mention that the same code with Mockito works as expected.

Expected Behavior

The intent spy is properly built and activity launched.

Current Behavior

The intent used to launch an activity raises an error.

Steps to Reproduce

  1. Spy an Android intent
  2. Mock a call to get intent extra
  3. Launch the activity with ActivityTestRule

Context

Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

Stack trace

// -----------------------[ YOUR STACK STARTS HERE ] -----------------------

java.lang.RuntimeException: Could not launch activity
at androidx.test.runner.MonitoringInstrumentation.startActivitySync(MonitoringInstrumentation.java:495)
at androidx.test.rule.ActivityTestRule.launchActivity(ActivityTestRule.java:358)
at com.owncloud.android.flow.CreatePublicShareTest.setUp(CreatePublicShareTest.kt:188)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:76)
at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:531)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:392)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
Caused by: java.lang.NoSuchMethodException: migrateExtraStreamToClipData []
at java.lang.Class.getMethod(Class.java:2068)
at java.lang.Class.getDeclaredMethod(Class.java:2047)
at io.mockk.proxy.android.MethodDescriptor.getMethod(MethodDescriptor.kt:22)
at io.mockk.proxy.android.advice.Advice.getOrigin(Advice.kt:37)
at java.lang.reflect.Method.invoke(Native Method)
at io.mockk.proxy.android.AndroidMockKDispatcher.getOrigin(AndroidMockKDispatcher.java:117)
at android.content.Intent.migrateExtraStreamToClipData(Unknown Source:14)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1666)
at androidx.test.runner.MonitoringInstrumentation.execStartActivity(MonitoringInstrumentation.java:536)
at android.app.ContextImpl.startActivity(ContextImpl.java:917)
at android.app.Instrumentation.startActivitySync(Instrumentation.java:492)
at android.app.Instrumentation.startActivitySync(Instrumentation.java:435)
at androidx.test.runner.MonitoringInstrumentation.access$201(MonitoringInstrumentation.java:99)
at androidx.test.runner.MonitoringInstrumentation$4.call(MonitoringInstrumentation.java:471)
at androidx.test.runner.MonitoringInstrumentation$4.call(MonitoringInstrumentation.java:468)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)

// -----------------------[ YOUR STACK TRACE ENDS HERE ] -----------------------

Minimal reproducible code (the gist of this issue)

// -----------------------[ GRADLE DEFINITIONS ] -----------------------
testImplementation "io.mockk:mockk:$mockkVersion"
    androidTestImplementation ("io.mockk:mockk-android:$mockkVersion") {
        exclude module: 'objenesis'
    }
// -----------------------[ YOUR CODE STARTS HERE ] -----------------------
package com.owncloud.android.flow

import android.content.Intent
import androidx.test.rule.ActivityTestRule
import com.owncloud.android.ui.activity.FileActivity
import io.mockk.every
import io.mockk.spyk
import org.junit.Rule
import org.junit.Test

class Issue94Test {
    @Rule
    @JvmField
    val activityRule = ActivityTestRule(
        DetailsActivity::class.java,
        true,
        false
    )

    @Test
    fun test() {
        val intent = spyk<Intent>()
        val exampleText = "text"
        every { intent.getStringExtra(DetailsActivity.EXTRA_TEXT) } returns exampleText
        intent.putExtra(DetailsActivity.EXTRA_TEXT, exampleText)
        activityRule.launchActivity(intent)
    }
}
// -----------------------[ YOUR CODE ENDS HERE ] -----------------------
stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. If you are sure that this issue is important and should not be marked as stale just ask to put an important label.

RishavChudal commented 4 years ago

Hi @oleksiyp, is this bug when we try to mock "Intent" also?

gustavobarbosab commented 2 years ago

I had a problem like that...

I have tried making a spyk<Intent>() and returning a default value from the method getIntExtra, the behavior has been returning the value 0.

Note: I would like to test the call's intent.getIntExtra("MY_KEY", 10) and ensure that default value was 10.

@Test
    fun `Test if the default value is 10`() {
        // WHEN
        val id = intent.getIntExtra("MY_KEY", 10)

        // THEN
        Assert.assertEquals(10, id)
    }