Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android Test: ClassCastException: org.mockito.Answers cannot be cast to org.mockito.stubbing.Answer #39

Closed
cypressious opened this issue Jun 17, 2016 · 9 comments

Comments

@cypressious
Copy link

cypressious commented Jun 17, 2016

I'm getting the following exception when I try to run a test that previously worked without mockito-kotlin:

java.lang.ClassCastException: org.mockito.Answers cannot be cast to org.mockito.stubbing.Answer
at com.nhaarman.mockito_kotlin.CreateInstanceKt.uncheckedMock(CreateInstance.kt:178)
at com.nhaarman.mockito_kotlin.CreateInstanceKt.createInstance(CreateInstance.kt:58)

I'm trying to isolate the code that is causing it.

Using version 0.5

@cypressious cypressious changed the title ClassCastException: org.mockito.Answers cannot be cast to org.mockito.stubbing.Answer Android Test: ClassCastException: org.mockito.Answers cannot be cast to org.mockito.stubbing.Answer Jun 17, 2016
@nhaarman
Copy link
Collaborator

Could this have something to do with #35?

@cypressious
Copy link
Author

Here's a test case to reproduce it:

class KotlinMockitoTest {
    @Test
    fun test() {
        val mock = mock<Func1<String, String>>()
        whenever(mock.call(any())).thenReturn("foo")
        assertEquals("foo", mock.call("bar"))
    }
}

Func1 is any Java interface, like the one from RxJava.

Since the test is run as an android instrumentation test, I should mention that I had to force an older mockito dependency, because mockito 2.0 doesn't work with dexmaker. My dependencies are declared as follows.

androidTestCompile 'org.mockito:mockito-core:1.9.5'
androidTestCompile('com.nhaarman:mockito-kotlin:0.5.0') {
    exclude group: 'org.jetbrains.kotlin'
    exclude group: 'org.mockito'
}
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'

@AdrianAtHumboldt
Copy link

I believe the older Mockito version is the cause: I also had this issue in a (non-Android) project using an older Mockito version, and resolved by upgrading to Mockito 2.0.

@pvorb
Copy link

pvorb commented Jul 12, 2016

I use Mockito 1.10.19 since Mockito 2 is still in beta and also face this issue.

Maybe I can find a way to achieve the same functionality in a way compatible to both Mockito 1 and 2 and come up with a patch.

@pvorb
Copy link

pvorb commented Jul 14, 2016

I ended up with something like this

@Suppress("UNCHECKED_CAST")
private fun <T> Class<T>.uncheckedMock(): T {
    // use fallback for pre 2.0 Mockito versions
    val defaultAnswer: Answer<*> =
            if (Answers.RETURNS_DEFAULTS is Answer<*>)
                Answers.RETURNS_DEFAULTS
            else
                GloballyConfiguredAnswer()

    val impl = MockSettingsImpl<T>().defaultAnswer(defaultAnswer) as MockSettingsImpl<T>
    val creationSettings = impl.confirm(this)
    return MockUtil().createMock(creationSettings).apply {
        if (this is Any && this.javaClass.simpleName == "MockAccess") {
            (this as MockMethodInterceptor.MockAccess).mockitoInterceptor = null
        }
    }
}

But unfortunately suddenly I was unable to reproduce the ClassCastException when reverting back to the version without this change, even with your test case from above.

@cypressious Could you check if the above code snippet works for you?

@nhaarman
Copy link
Collaborator

If anyone could make a PR with a solid test that fails with this issue, we could try and tackle it.

@zeitlinger
Copy link

I can confirm that this problem exists before Mockito 2.

This is the test case that I used to check

    @Test
    fun verifyTest() {
        open class Klass {
            open fun doIt(list: List<String>) {

            }
        }

        val klass: Klass = mock()

        val c: ArgumentCaptor<List<String>> = argumentCaptor()

        klass.doIt(ArrayList())

        verify(klass).doIt(capture(c))
    }

@nhaarman
Copy link
Collaborator

nhaarman commented Sep 9, 2016

It looks like this issue and #35 are caused by using Mockito 1.x. This library really focuses on the soon-to-be-released 2.x version.

@nimloth05
Copy link

I believe the randomness of this problem stems from classloaders loading multiple versions of mockito. I had the same problem even after upgrading kotlin_mockito to 0.11. Juckito, another support library for mockito, uses version 1.x of Mockito.

Move the juckito declaration or any other library which pulls in Mockito 1.x to the end of the include list. I add this comment, because google led me here (first hit of my search)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants