Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin Coroutine Unit Testing Error: Exception in thread "main @coroutine#1 @coroutine#2" java.lang.NullPointerException

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?

like image 889
Ben987654 Avatar asked Nov 30 '25 02:11

Ben987654


1 Answers

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.

like image 141
Ben987654 Avatar answered Dec 02 '25 16:12

Ben987654



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!