20

I'm trying to unit test a presenter that I made with Kotlin coroutines, and this is also my first time using Mockito

Whenever I try to run the unit test I'm getting the following error the first time it tries to do anything with my view while in the coroutine

Exception in thread "main @coroutine#1 @coroutine#2" java.lang.NullPointerException
    at .signin.SignInPresenter$subscribe$1.doResume(SignInPresenter.kt:45)
    at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:54)
    at kotlinx.coroutines.experimental.DispatchedKt.resumeCancellable(Dispatched.kt:208)
    at kotlinx.coroutines.experimental.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:35)
    at kotlinx.coroutines.experimental.CoroutineStart.invoke(CoroutineStart.kt:111)
    at kotlinx.coroutines.experimental.AbstractCoroutine.start(AbstractCoroutine.kt:161)
    at kotlinx.coroutines.experimental.BuildersKt.launch(Builders.kt:68)
    at kotlinx.coroutines.experimental.BuildersKt.launch$default(Builders.kt:61)
    at .signin.SignInPresenter.subscribe(SignInPresenter.kt:42)

This is the relevant part of my presenter, the line referenced in the error is view.showSigninPanel

class SignInPresenter(
    private val view: SignInContract.View,
    private val userRepo: ParseAuthController,
    private val contextPool: CoroutineContextProvider
) : SignInContract.Presenter {

    private val coroutineJobs: MutableList<Job> = mutableListOf()

    override fun subscribe() {
        view.loadBackgroundImage()
        view.setUpSignInPanel()
        view.setUpKeyboardListener()

        coroutineJobs.add(launch(contextPool.Main) {
            if (!userRepo.isAuthenticated()) {
                view.showSignInPanel()
                subscribeToLoginValidation()
                subscribeToPaswordEmailValidation()
            } else {
                view.launchMainActivity()
            }
        })
    }

The call to userRepo.isAuthenticated() is a suspended call

I'm passing in a test coroutine context into my presenter as per this article

https://android.jlelse.eu/mastering-coroutines-android-unit-tests-8bc0d082bf15

class TestContextProvider : CoroutineContextProvider() {
    override val Main: CoroutineContext = Unconfined
    override val IO: CoroutineContext = Unconfined
}

This is my unit test currently

class SignInPresenterTest {

    private lateinit var view: SignInContract.View
    private lateinit var presenter: SignInPresenter
    private lateinit var parseAuthController: ParseAuthController

    @Before
    fun setUp() {
        view = mock(SignInContract.View::class.java)

        parseAuthController = mock(ParseAuthController::class.java)

        presenter = SignInPresenter(
            view,
            parseAuthController,
            TestContextProvider()
        )
    }

    @After
    fun tearDown() {
        presenter.dispose()
    }

    @Test
    fun subscribeNotAuthenticatedShowSignInPanel() {
        runBlocking {
            val expectedResult = false
            `when`(parseAuthController.isAuthenticated()).thenReturn(expectedResult)

            presenter.subscribe()
        }

        verify(view).showSignInPanel()
    }
}

UPDATE: I've been doing some additional tests, and it looks like if I remove the suspend call within my presenter if (!userRepo.isAuthenticated()) it won't crash and I can verify if something has run with Mockito, but this isn't an actual solution... but something with that suspending call is causing problems?

2
  • can you share code please, I have the same problem, lib is updated but don't work Commented May 20, 2019 at 8:14
  • I don't have access to this codebase anymore. Maybe try doing a ./gradlew build --refresh-dependencies and see if that fixes it? Commented May 21, 2019 at 22:43

1 Answer 1

4

Problem solved!

The above code is actually correct. I had the wrong Mockito dependency.

I was copying some dependencies from a co-workers repo and they were using this library that provides some Kotlin specific functionality

https://github.com/nhaarman/mockito-kotlin

Either there's something in there breaking support for coroutines, or maybe there's some different requirements to make it work?

Updating to the latest Mockito dependency works.

Sign up to request clarification or add additional context in comments.

1 Comment

I did also have this lib, but I removed ti and still see this result.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.