question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

java.lang.ClassCastException: kotlin.Result cannot be cast to java.util.List

See original GitHub issue

Prerequisites

Please answer the following questions for yourself before submitting an issue.

  • I am running the latest version
  • I checked the documentation and found no answer
  • I checked to make sure that this issue has not already been filed

Expected Behavior

I’m testing a class that has a suspend fun and returns Result<List<..>>. In a unit test I’m mocking this class and want to return a Result.success(...) from that method. Expecting that my mock returns that value when called, but it crashes instead.

First I thought it’s a Kotlin bug and wanted to file an issue there, however, in production and when removing the mockk calls, the code works as expected, so I assume it’s instead a mockk bug.

This sample code snippet:

class ExampleUnitTest {

    private val testClass = mockk<TestClass>()

    @Test
    fun `test bug`() = runBlockingTest {
        coEvery { testClass.execute() } returns Result.success(listOf("1"))

        testClass.execute()
          .fold(
            onSuccess = {
                println(it)
            },
            onFailure = {
                println("fail")
            }
          )
    }
}

class TestClass {

    suspend fun execute(): Result<List<String>> {
        return suspendCoroutine {
            it.resume(Result.success(listOf("")))
        }
    }
}

crashes with

java.lang.ClassCastException: kotlin.Result cannot be cast to java.util.List

	at de.syex.resultbug.ExampleUnitTest$test bug$1.invokeSuspend(ExampleUnitTest.kt:24)
	at de.syex.resultbug.ExampleUnitTest$test bug$1.invoke(ExampleUnitTest.kt)
	at kotlinx.coroutines.test.TestBuildersKt$runBlockingTest$deferred$1.invokeSuspend(TestBuilders.kt:50)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
	at kotlinx.coroutines.test.TestCoroutineDispatcher.dispatch(TestCoroutineDispatcher.kt:50)
	...

The offending line 24 is the fold(). I found this issue while testing some code that actually runs fine. Instantiating TestClass instead

private val testClass = TestClass()

lets the test pass as expected.

  • MockK version: 1.10.0
  • Kotlin version: 1.4.0
  • Coroutine version: 1.3.9
  • JDK version: 1.8
  • JUnit version: 4.12 & 5.6.2
  • Gradle version: 6.1.1 & 6.5.1
  • Type of test: unit test

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:17
  • Comments:17 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
dkuteynikovcommented, Jul 2, 2021

I have reported it straight to the Kotlin team: https://youtrack.jetbrains.com/issue/KT-46477#focus=Comments-27-4952485.0-0 Because it is a language-level bug.

2reactions
Raibazcommented, May 14, 2021

I’ve seen the implementation that has been done in Mockito to handle this.

It seems like we can replicate it in mockk, it’s basically about trying to unbox the underlying value contained in the Result class if possible and returning it in the answerer.

However, it’s only feasible from Kotlin 1.5.0 onwards, because it requires the @JvmInline annotation to be available and set on the Result class (or any other inline class, for that matter).

Given the fact that 1.5.0 was released very recently and using Result as a return type is not possible by default but it requires the -Xallow-result-return-type kotlin option to be set, this doesn’t look to me like a high priority issue right now.

Reopening it for now and leaving it here in case anyone wants to submit a PR.

Read more comments on GitHub >

github_iconTop Results From Across the Web

ClassCastException: foo.Bar cannot be cast to kotlin.Result
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to kotlin.Result at org.example.App$onCreate$1.invokeSuspend( App.kt:65 ) ...
Read more >
ClassCastException: <type> cannot be cast to kotlin.Result
One of the surprising features in Kotlin 1.3 release was built in functional Either monad implementation called Result.
Read more >
Result nested twice when collecting a Flow in Kotlin 1.5 (kotlin ...
Show activity on this post. I have The same issue I downgraded the kotlin version from 1.5. 10 to 1.4. 32 and the...
Read more >
How to fix java.lang.classcastexception cannot be cast to in Java
As name suggests ClassCastException in Java comes when we try to type cast an object and object is not of the type we...
Read more >
kotlin.Result cannot be cast to java.util.List - Bountysource
java.lang.ClassCastException: kotlin.Result cannot be cast to java.util.List at de.syex.resultbug.ExampleUnitTest$test bug$1.invokeSuspend( ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found