the_new_mr
the_new_mr

Reputation: 3733

Kotlin Unit testing - How to mock component of Companion object?

If I have a (simplified) class that looks like this:

class MyManager @JvmOverloads constructor(/*constructor args*/) : MyManagerInterface {

    @Inject
    lateinit var myLogger: MyLogger

    init {
        component = DaggerLoggerComponent.builder()
                .loggerModule(LoggerModule(internalLogger))
                .build()

        component.inject(this)
    }

    companion object {
        lateinit var component: RemoteLoggerComponent
            private set
    }
}

When unit testing, how on earth do I mock the component in the companion object?

I've tried all kinds of tricks using Mockito, MockK etc but I come up against several obstacles.

The CUT (class-under-test) is another class that is using the MyManager component to inject its dependencies in its init block like so:

init {
        if(applicationContext == null) {
            throw IllegalStateException("Application Context must not be null")
        } else {

            MyManager.component.inject(this)
        }
    }

Basically, I'd be happy if the injection does nothing because I can set the dependencies externally for the sake of testing.

All help appreciated. Including if you think I'm coding this wrong. I'm relatively new to Kotlin and Dagger. Thanks.

Upvotes: 31

Views: 24754

Answers (2)

Kartal Tabak
Kartal Tabak

Reputation: 894

Do not forget to unmock companion objects. Otherwise, mocked version shall be used after the current test.

Blocked mocking shall unmock automatically for us:

mockkObject(MyManager) {
  every { MyManager.component.someOp(...) } returns 5

  act() 

  verify {
    ...
  }

}

Upvotes: 2

oleksiyp
oleksiyp

Reputation: 3107

Basically, using MockK, you need code like that:

mockkObject(MyManager)
every { MyManager.component.someOp(...) } returns 5

Not sure I understand all the details about the injection. As you said you can disable it.

Upvotes: 55

Related Questions