Trying to use runBlockingTest for my unit tests, and getting the above-mentioned error.
Here are my code snippets:
@Test
fun `test verify test call`() = runBlockingTest {
registerViewModel.testCall()
verify(repo).suspendedTestCall()
}
fun testCall() {
viewModelScope.launch(Dispatchers.IO) {
repository.suspendedTestCall()
}
}
suspend fun suspendedTestCall() {
kotlinx.coroutines.delay(2_000)
}
Also getting the same error when trying to use TestCoroutineDispatcher.
Full log:
java.lang.NoSuchMethodError: kotlinx.coroutines.SupervisorKt.SupervisorJob$default(Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob;
at kotlinx.coroutines.test.TestBuildersKt.checkArguments(TestBuilders.kt:94)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:46)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest$default(TestBuilders.kt:45)
at at.rollingpin.register.RegisterViewModelTest.test verify test call(RegisterViewModelTest.kt:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
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 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
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.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
What's your environment? How do you get this problem?
What exactly do you mean by environment?
Also another thing - I made it work by injecting the dispatcher. Meaning it won't work without injecting the CoroutineDispatcher, correct me if I'm wrong?
Calls to withContext(Dispatchers.IO) or withContext(Dispatchers.Default) are common in coroutines based codebases. Both dispatchers are not designed to interact with TestCoroutineDispatcher.
Tests should provide a TestCoroutineDispatcher to replace these dispatchers if the withContext calls delay in the function under test. For example, a test that calls veryExpensiveOne should provide a TestCoroutineDispatcher using either dependency injection, a service locator, or a default parameter.
came across this on the github page
Calls to withContext(Dispatchers.IO) or withContext(Dispatchers.Default) are common in coroutines based codebases. Both dispatchers are not designed to interact with TestCoroutineDispatcher.
Tests should provide a TestCoroutineDispatcher to replace these dispatchers if the withContext calls delay in the function under test. For example, a test that calls veryExpensiveOne should provide a TestCoroutineDispatcher using either dependency injection, a service locator, or a default parameter.came across this on the github page
Does it mean that whenever I need to use Dispaters.IO or Dispatcher.Default I have to provide it using dependency injection so that I can test it in the future? Or I incorrect get it?
It depends on your testing strategy.
Same issue here
java.lang.NoSuchMethodError: kotlinx.coroutines.SupervisorKt.SupervisorJob$default(Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob;
at kotlinx.coroutines.test.TestBuildersKt.checkArguments(TestBuilders.kt:94)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:46)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest$default(TestBuilders.kt:45)
@Test
fun `test login behavior`() = runBlockingTest {
userRepository.login(USERNAME, PASSWORD)
coVerify {
val user = remoteUserDao.login(USERNAME, PASSWORD)
localUserDao.insert(user)
}
}
class UserRepositoryImpl(
private val remoteUserDao: RemoteUserDao,
private val localUserDao: LocalUserDao
) : UserRepository {
override suspend fun login(username: String, password: String): User {
val user = remoteUserDao.login(username, password)
localUserDao.insert(user)
return user
}
}
Kotlin version: 1.3.41
kotlinx-coroutines-test version: 1.3.0-M2
Android studio version: 3.4.2
JUnit version: 4.12
Mockk version: 1.9.3
Can you, please, check that your kotlinx-coroutines-core and kotlinx-coroutines-test versions match.
In my case, using
runBlockingTest {
}
every time throws error:
java.lang.NoSuchMethodError: kotlinx.coroutines.SupervisorKt.SupervisorJob$default(Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob;
at kotlinx.coroutines.test.TestBuildersKt.checkArguments(TestBuilders.kt:94)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:46)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest$default(TestBuilders.kt:45)
at com.jakmos.itemistevolved.useCase.InsertChecklistUseCaseTest.executeSuccess(InsertChecklistUseCaseTest.kt:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
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 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
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.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
on every version coroutines-test newer than:
kotlinx-coroutines-test version: 1.3.0-M1
My Kotlin plugin version: 1.3.41
Android studio version: 3.4.2
Does your version of kotlinx-coroutines-test matches with the version of kotlinx-coroutines-core?
I thought kotlinx-coroutines-core is included to Kotlin itself. I haven't imported that package before, but after the error occurred I did, only to check if it's gonna fix the problem (it didn't), even when kotlinx-coroutines-core version was matching the kotlinx-coroutines-test.
@JakubMosakowski Is there any chance you can create and share a small project that would demonstrate the problem that you are experiencing?
Sure, here it is: https://github.com/JakubMosakowski/test-project-coroutines
During preparing the test-project I found out that if I remove those 2 imports there is no error:
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0-rc01"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0-rc01"
FWIW I'm hitting the same issue. Backporting to org.jetbrains.kotlinx:kotlinx-coroutines-test:1.2.2 seems to resolve the issue for me until a root cause is known.
The problem here is not in the library itself but in transitive dependencies.
In Android Studio or IntelliJ IDEA press Find symbol hotkey (cmd/ctrl+ N) and type kotlinx.coroutines.Job.
If you see more than two versions of the class (example), it's a dependency clash.
You have multiple options here:
1) Check whether dependencies that rely on coroutines can be updated and update them, if so
2) Explicitly add kotlinx-coroutines-core (additionally to kotlinx-coroutines-android or kotlinx-coroutines-test or any other kx-coroutines dependency) with the desired version to your dependencies
3) Resolve to the desired version of kotlinx.coroutines explicitly using custom Gradle resolution strategy
@JakubMosakowski thanks for the reproducer!
Yep, It works.
Before adding custom Gradle resolution strategy:

After:

Thanks for your help!
Just in case anyone else ends up here with this issue and finds that adding the resolutionStrategy not working in app/build.gradle, someone pointed me to adding it to the top level build.gradle in the allprojects block.
allprojects {
repositories {
...
}
configurations.all {
resolutionStrategy {
force "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion"
force "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesVersion"
force "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutinesVersion"
}
}
}
ext { kotlinCoroutinesVersion = '1.3.4' }
Most helpful comment
Does your version of
kotlinx-coroutines-testmatches with the version ofkotlinx-coroutines-core?