-
-
Notifications
You must be signed in to change notification settings - Fork 351
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
Issue with mocking value classes with coEvery #1073
Comments
I'm facing the same issue with Kotlin 1.8.0+ (1.8.20 as well). Here is an even shorter example:
Removing the |
Facing the same issue, using functional interfaces (#1089). |
Basically facing the same issue as @Wrakor for a quite long time and it is very annoying. More example showing the issue can be found in my project's test class. From my experience, the combination below fails when mocking:
However, in commercial projects where I use |
Any updates? There is something really lacking here. I've noticed that If I have the following UseCase:
This mock works without any issue: But if I rewrite the same interface as It will have the error mentioned at the start of this thread.
|
Are there any updates? |
I struggled with this as well, until I realized that, since a For example, in the example above: fun interface GetNearbyPostalCodesUseCase : suspend (Address?) -> Result<List<PostalCode>> we can simply define the following in our test: val getNearbyPostalCodesUseCase = GetNearbyPostalCodesUseCase {
Result.success(mockPostalCodes)
} and call |
Yes, you can manually define the use case, but that would be a workaround of the underlying issue, which is not being able to mock with |
Any updates on this? |
@Raibaz will you be able to take a look on this issue or at least point me into the direction where to fix it? It's a real blocker for my team in order to finish the migration from the Mockito and I would love to help to solve it. Thank you and appreciate your help! 🙏 |
While I think @abcarrell's reasoning is correct and mocking interfaces is generally not a good idea, I understand the need to fix this issue: perhaps looking into the changes that were introduced in #1253 and around that part of the codebase could help. |
Here is a reproduction of the issue: https://github.com/mkotsbakws/mockk-reproducer
|
Makes sense, #1202 adds an automatic unboxing to support nested value class, which breaks this case. We should add logic to determine whether a value class has another nested value class inside and do the autounboxing only in that case; I'd gladly review a PR that adds this. |
Just to add to this, I think it's related. The following works wit 1.13.12 but fails with 1.13.13: @JvmInline
private value class MyId(private val id: String)
private interface Y {
suspend fun getId(): MyId?
}
private class X(private val y: Y) {
suspend fun doStuff(): MyId? = y.getId()
}
@Test
fun `test stuff`() {
val mocked = mockk<Y>()
coEvery { mocked.getId() } returns MyId("987")
runBlocking { X(mocked).doStuff() } shouldBe MyId("987")
} Error message:
|
Yes, I tried to reproduce with wrapped value class in value class (including generic parameter), but did not, also with async, but only succeeded with Result. Not sure what is special with Result. Maybe "@kotlin.internal.InlineOnly" or that wrapped value is only available through getter. |
I noticed there are a lot of tests related to value classes that are disabled. Errors expected then... |
…ses with coEvery. Enable few disabled tests for support nested value classes (issue: 859)
…value-classes-with-coEvery Fix( Issue #1073): Bug fix for the issue with mocking value classes with coEvery
Is there a plan for a next release? |
Just published v1.13.16 :) |
still failing using 1.13.16 interface InterfaceWithResult {
suspend fun getResult(): Result<Boolean>
}
@Test
fun `test failing`() = runTest {
val mockedInterface = mockk<InterfaceWithResult>()
coEvery {
mockedInterface.getResult()
} returns Result.success(false)
val result = mockedInterface.getResult().getOrNull() // failing here
} getting the error class kotlin.Result cannot be cast to class java.lang.Boolean (kotlin.Result is in unnamed module of loader 'app'; java.lang.Boolean is in module java.base of loader 'bootstrap') |
Yeah, looks like this only works for Strings. At the same time, the PR seems to break some regular cases. |
@swa-chacor If you want to use
|
@sschuberth |
@kpadhiamex it could technically work but I don't want to change my interface to generics. |
We started experiencing issues with many of our tests after the bump to 1.13.16
these fails when calling a internal class GetOnboarding {
suspend operator fun invoke(): Result<Onboarding> {
return enrollRepository.getOnboarding()
}
} |
…ses with coEvery. Enable few disabled tests for support nested value classes (issue: 859)
@kpadhiamex makes sense, please go ahead with the revert. Thanks! |
Hello, this bug still occurs on 1.13.16 |
v1.13.16 fixed our issue 👍 |
The issue started reproducing after the update to 1.13.16, it was not faced in 1.13.14 though. |
Hi there! I'm seeing this with |
You probably mean the latest? I did the bisect and concluded the latest working for us is 1.13.9. |
Yes, sorry, you were right. I meant the "earliest version going backwards". 🙂 FWIW, I was able to work around my problem as described here: #1098 (comment) |
Prerequisites
Please answer the following questions for yourself before submitting an issue.
Failure Information (for bugs)
I'm running into an edge case issue with value classes being used as mock answers for suspending methods that implement an interface with generics.
Consider the following interface with an implementing class using Kotlin
Result
(or any other value class)and a simple test like
it fails with
when calling
resultTest.execute(Unit)
.With a modification of the return type of the interface method
execute
fromReturnType
toResult<ReturnType>
:the same test will pass.
The test will also pass with the first version of the interface if I remove the
suspend
keyword and replacecoEvery
withevery
.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
The text was updated successfully, but these errors were encountered: