Koin DI Android Unit testing ViewModel

Viewed 1842

I use Koin DI in my app, and everything works fine. I have injected viewModels without no issue.

Eg, I have a calcViewModel with function:

class CalcViewModel(): ViewModel() {
    fun calculateNumber(): Int{
        var a = 5 + 3
        return a
    }
}

And in the app I use it like this:

class Application : Application() {
    override fun onCreate() {
        super.onCreate()

        startKoin {
        // androidContext(this@MyApp)
        androidLogger(Level.DEBUG)
        androidContext(this@Application)
        modules(
            listOf(
                myModule
            )
        )
    }

And in my appModule file:

val myModule= module {
    viewModel { CalcViewModel() }
}

And in the app, whenever I need my viewModel instance, I just use:

private val calcViewModel by viewModel<CalcViewModel>()

And as I said, everything works perfectly but when I try to write a simple unit test for this function

fun calculateNumber(): Int{
        var a = 5 + 3
        return a
}

from the view model I have null pointer.

This is the test Class I tried

class CalcViewModelTest: KoinTest{

val calcViewModel:CalcViewModel by inject()

@Before
fun setup() {

    startKoin {
        module { single { myModule} }
      
    }
}

@Test
fun calculateNumber(){
    val result = calcViewModel.calculateNumber()  // here I get that error when trying to access calcViewModel var
    Assert.assertEquals(result,8)
}

@After
fun tearDown() {
    stopKoin()
}

}

And everytime I get this error when I try to run my unit test:

org.koin.core.error.NoBeanDefFoundException: No definition found for 
class:'com.package.CalcViewModel'. Check your definitions!

Also if I use the same way to fetch the viewModel in test class like in the app:

val calcViewModel by viewModel<CalcViewModel>()

It uses a different constructor that asks for 3 params (class, owner, scope)

I also imported in the gradle:

testImplementation "org.koin:koin-androidx-viewmodel:$koin_version"
testImplementation "org.koin:koin-test:$koin_version"

Did anyone tried to write unit tests with Koin and using viewModels ?

Thanks

2 Answers

Based on Koin Documentation, you need to use by inject() to create instance of class.

    val calcViewModel by inject<CalcViewModel>()

Then, create koinTestRule like this.

    @get:Rule
    val koinTestRule = KoinTestRule.create {
        printLogger()
        modules(myModule)
    }

In the end I just initialized the viewModel and used the instance.

 private lateinit var viewModel: CalcViewModel

and later in setUp()

viewModel = CalcViewModel()
Related