3

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

Adrian Ivasku
  • 1,118
  • 3
  • 16
  • 31
  • 1
    it should be modules not module – Blackbelt Sep 05 '20 at 16:38
  • @Blackbelt It is just another way of loading modules, if you use module like I did you can add one module, if use modules it expects list of modules. I tried with list of modules too, no luck. In the app works great but I cannot unit test it. – Adrian Ivasku Sep 05 '20 at 16:41
  • 1
    the documentations says to use `modules` not `module` with `startKoin`. `module` seems to be to declare (create) a module, but I don't have much experience with koin – Blackbelt Sep 05 '20 at 16:44
  • @Blackbelt I just tried like that too just to be 1000% sure, startKoin { modules ( listOf( myModule) )} and the same error as before. – Adrian Ivasku Sep 05 '20 at 16:47

2 Answers2

0

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)
    }
-2

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

 private lateinit var viewModel: CalcViewModel

and later in setUp()

viewModel = CalcViewModel()
Adrian Ivasku
  • 1,118
  • 3
  • 16
  • 31