How to write unit tests for kotlin coroutines

2019-08-23 07:34发布

I am trying to unit test the kotlin coroutines. My project is following MVP pattern where the coroutines are used in the presenter like this:

fun authenticateWithUserAndPassword(usernameOrEmail: String, password: String) {
        launchUI(strategy) {
            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 launchUI is defined as

/**
 * Launches a coroutine on the UI context.
 *
 * @param strategy a CancelStrategy for canceling the coroutine job
 */
fun launchUI(strategy: CancelStrategy, block: suspend CoroutineScope.() -> Unit): Job =
    MainScope().launch(context = strategy.jobs, block = block)

CancelStrategy 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 to coroutine unit testing and tried writing a basic unit test

@Test
fun check_authentication_of_user() = runBlocking {
    loginPresenter.authenticateWithUserAndPassword(USERNAME, PASSWORD)
    verify(navigator).toChatList()
}

On running the test I am getting the following error.

java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlinx.coroutines.BuildersKt__Builders_commonKt.launch, parameter context

Any help regarding how to unit test the given method will be appreciated.

0条回答
登录 后发表回答