0

i am trying to mock a repository class using declareMock and mockk but it doesn't seem to be working as i am getting the data from the real repository.

Version

implementation "org.koin:koin-androidx-viewmodel:2.1.6"
testImplementation "org.koin:koin-test:2.1.6"

Code

My application class (only relevant parts):

class MyApplication : Application() {
    companion object {
        val appModule = module {
            single<RepositoryUserLists> { RepositoryUserListsImpl() }
        }
    }

    override fun onCreate() {
        super.onCreate()

        startKoin {
            androidLogger()
            androidContext(this@MyApplication)
            modules(appModule)
        }
    }
}

My test class (only relevant parts)

class TestRepositoryUserLists : KoinTest {
    @get:Rule
    val koinTestRule = KoinTestRule.create {
        modules(MyApplication.appModule)
    }

    @get:Rule
    val mockProvider = MockProviderRule.create { clazz ->
        mockkClass(clazz.java.kotlin)
    }

    @Rule
    @JvmField
    val instantExecutorRule = InstantTaskExecutorRule()

    private val repo: RepositoryUserLists by inject()

    @Before
    fun before() {
        declareMock<RepositoryUserLists> {
            every { getAllLists() } returns MutableLiveData(listOf(MyList("test list")))
        }
    
        //PROBLEM IS HERE
        //Expected: a list containing one item names "test list".
        //Actual: empty list (like in real repository).
        repo.getAllLists().value 
    }
}

github issue: https://github.com/InsertKoinIO/koin/issues/841

Feedbacker
  • 890
  • 6
  • 17
or_dvir
  • 479
  • 1
  • 7
  • 22

2 Answers2

1

Just posted it here for those migrating to a newer version of the koin like 2.2.2, and the dependency test was failed with an error Missing MockProvider. Please use MockProvider.register() to register a new mock provider.

import io.mockk.every
import io.mockk.mockkClass
...

val app = koinApplication {
    printLogger(Level.DEBUG)
    modules(...)
}

MockProvider.register { mockkClass(it) }

with(app.koin) {
    declareMock<MyService> {
        every { someAction() } returns "some answer"
        ...
    }
}

app.checkModules()
Grigory K
  • 1,301
  • 10
  • 10
0

I think you need to use the given/will syntax inside the declareMock block

    declareMock<RepositoryUserLists> {
        given(getAllLists()).willReturn(MutableLiveData(listOf(MyList("test list"))))
    }
Feedbacker
  • 890
  • 6
  • 17
  • this is not the syntax for `mockk` – or_dvir Jun 29 '20 at 13:10
  • I believe that is the whole point. Koin uses the `mockProvider` *you* provide and mocks it for you. Therefore, inside `declareMock` you need to use the koin mock functions. – Feedbacker Jun 29 '20 at 13:29
  • i got io.mockk.MockKException: no answer found for: RepositoryUserLists(#1).getAllLists() – or_dvir Jun 29 '20 at 18:04
  • I am not sure if it helps but in my project instead of a Rule I use `startKoin`. Maybe something like this works? `startKoin { modules(MyApplication.appModule) }` – Feedbacker Jun 30 '20 at 16:19
  • thanks for the comment, but for now i just use a fake repository which i managed to inject. ill try this when i feel like trying this again – or_dvir Jun 30 '20 at 20:19