Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

kotlin

mockk

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.

like image 427
the_new_mr Avatar asked Aug 10 '18 18:08

the_new_mr


People also ask

How do you call a method inside a companion object in Kotlin?

However, in Kotlin, you can also call callMe() method by using the class name, i.e, Person in this case. For that, you need to create a companion object by marking object declaration with companion keyword.

How do you use the companion object in Kotlin?

To create a companion object, you need to add the companion keyword in front of the object declaration. The output of the above code is “ You are calling me :) ” This is all about the companion object in Kotlin. Hope you liked the blog and will use the concept of companion in your Android application.

Which objects or methods do you mock in a unit test?

Mocking for unit testing is when you create an object that implements the behavior of a real subsystem in controlled ways. In short, mocks are used as a replacement for a dependency.

Why do we create companion object in Kotlin?

There are times we need to use a companion object to define class members that are going to be used independently of any instance of that class. The Kotlin compiler guarantees we will have one and only one instance of a companion object.


2 Answers

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.

like image 175
oleksiyp Avatar answered Sep 19 '22 14:09

oleksiyp


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 {
    ...
  }

}
like image 36
Kartal Tabak Avatar answered Sep 20 '22 14:09

Kartal Tabak