I am trying to unit test the below function which uses kotlin coroutines
fun authenticateWithUserAndPassword(usernameOrEmail: String, password: String) {
launchUI(strategy) { //line 76
view.showLoading()
try {
val token = retryIO("login") {
when {
settings.isLdapAuthenticationEnabled() ->
client.loginWithLdap(usernameOrEmail, password)
usernameOrEmail.isEmail() ->
client.loginWithEmail(usernameOrEmail, password)
else ->
client.login(usernameOrEmail, password)
}
}
val myself = retryIO("me()") { client.me() }
myself.username?.let { username ->
val user = User(
id = myself.id,
roles = myself.roles,
status = myself.status,
name = myself.name,
emails = myself.emails?.map { Email(it.address ?: "", it.verified) },
username = username,
utcOffset = myself.utcOffset
)
localRepository.saveCurrentUser(currentServer, user)
saveCurrentServer.save(currentServer)
localRepository.save(LocalRepository.CURRENT_USERNAME_KEY, username)
saveAccount(username)
saveToken(token)
analyticsManager.logLogin(
AuthenticationEvent.AuthenticationWithUserAndPassword,
true
)
view.saveSmartLockCredentials(usernameOrEmail, password)
navigator.toChatList()
}
} catch (exception: RocketChatException) {
when (exception) {
is RocketChatTwoFactorException -> {
navigator.toTwoFA(usernameOrEmail, password)
}
else -> {
analyticsManager.logLogin(
AuthenticationEvent.AuthenticationWithUserAndPassword,
false
)
exception.message?.let {
view.showMessage(it)
}.ifNull {
view.showGenericErrorMessage()
}
}
}
} finally {
view.hideLoading()
}
}
}
here is the definition of launchUI
fun launchUI(strategy: CancelStrategy, block: suspend CoroutineScope.() -> Unit): Job =
MainScope().launch(context = strategy.jobs, block = block)
here is the cancel Strategy class
class CancelStrategy(owner: LifecycleOwner, val jobs: Job) : LifecycleObserver {
init {
owner.lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
jobs.cancel()
}
}
I am new with unit testing with coroutines and have written a very basic test for the above function to gets some hand on coroutine testing
@Test
fun authenticateUserSuccessfuly() = runBlocking {
loginPresenter.setupView()
loginPresenter.authenticateWithUserAndPassword("username", "password")
verify(view).showLoading()
verify(saveCurrentServer).save(currentServer)
}
On running the test I am getting the following error If someone can suggest how to test the above function It will be a great help.
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlinx.coroutines.BuildersKt__Builders_commonKt.launch, parameter context
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
at chat.rocket.android.util.extension.CoroutinesKt.launchUI(Coroutines.kt:15)
at chat.rocket.android.authentication.login.presentation.LoginPresenter.authenticateWithUserAndPassword(LoginPresenter.kt:76)
at chat.rocket.android.authentication.login.presentation.LoginPresenterTest$authenticateUserSuccessfuly$1.invokeSuspend(LoginPresenterTest.kt:101)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.kt:116)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:76)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:53)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:35)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at chat.rocket.android.authentication.login.presentation.LoginPresenterTest.authenticateUserSuccessfuly(LoginPresenterTest.kt:99)
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.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)