In kotest docs, it shows KoinExtension can be used...
# kotest
v
In kotest docs, it shows KoinExtension can be used in this way
Copy code
class KotestAndKoin : FunSpec(), KoinTest {

    override fun extensions() = listOf(KoinExtension(myKoinModule))

    val userService by inject<UserService>()

    init {
        test("use userService") {
            userService.getUser().username shouldBe "LeoColman"
        }
    }
}
But it does not work and crashes the test with KoinApplicationNotStarted Exception This is a snippet of my test
Copy code
class PostRepositoryTest : FunSpec(), KoinTest {

    override fun extensions() = listOf(
        KoinExtension(
            modules = listOf(dataModule),
            mockProvider = { mockkClass(it, relaxed = true) }
        )
    )


    private val apiService = declareMock<FeedMediaApiService>()
    private val socialRepo = declareMock<SocialRepository>()
    private val activityApiService = declareMock<ActivityApiService>()
    private val dataSource = declareMock<PostDataSource>()
    private val userRepo = declareMock<UserRepository>()

    private val postRepo by inject<PostRepository>()
This crashes, but if I change the vals to
lateinit var
and initialize them in
beforeTest
it works perfectly StackTrace:
Copy code
Caused by: java.lang.IllegalStateException: KoinApplication has not been started
	at org.koin.core.context.GlobalContext.get(GlobalContext.kt:36)
	at org.koin.core.component.KoinComponent$DefaultImpls.getKoin(KoinComponent.kt:33)
	at org.koin.test.KoinTest$DefaultImpls.getKoin(KoinTest.kt:32)
	at com.medial.app.data.repo.ugc.PostRepositoryTest.getKoin(PostRepositoryTest.kt:87)
	at com.medial.app.data.repo.ugc.PostRepositoryTest.<init>(PostRepositoryTest.kt:514)
Is there anything wrong in my code, or is the documentation incorrect??
e
Which version of Koin are you using?
v
Koin 3.5.3 Kotest-koin-extension 1.3.0
@Emil Kantis any info on this? Creating mocks in beforeTest increases test time by a lot I want to create mocks once, and just reset mocks by using MockK's
clearAllMocks()
before each test
e
I find that even using
declareMock
is not possible (compilation error), unless you add some definitely unwanted hack into your production code. Please provide a minimal sample if you want me to check it out further.
Otherwise you can feel free to raise a ticket regarding documenting a sample on how to use Kotest Koin extension with MockK and I can have a look at that more general problem
v
@Emil Kantis This is the reproducer, i have added both working and not working variations https://gist.github.com/Vaibhav2002/d7f0b6f11b56f10eabdf2af1c35a16c2
e
Creating the mocks inside the context will only create them once, assuming you're using the (default) Koste SingleInstance lifecycle
v
Understood Thanks for helping out
e
The example I posted should work just as posted, and you shouldn't need any
lateinit var
, or overriding of
test
youre welcome 👍
v
Yeah, i just find keeping tests out of
init
block a bit more readable This decreases test time a lot, around 69% decrease in test time in 3 such basic tests Thanks
e
I think it might be worthwhile to introduce a KoinProjectExtension which you could apply to the entire project and have the Koin context start before any test is run and being kept alive for the entire test execution. Is this something you would benefit from?
v
Yeah, that will help With that the Class under Test will be a fresh instance in every test and just the mocks remain the same?
e
The entire context would be re-used I believe.. but I could look at what the Koin APIs offer in terms of clearing non-mocks from the context
v
Yeah sure That would decrease test time by a lot
This is one of my test
Copy code
init {
    coroutineTestScope = true
    beforeEach {
        apiService = declareMock<UserApiService>()
        preferences = declareMock<Preferences>()
        dataSource = declareMock<PostDataSource>()
        declare<List<Tracker>> { emptyList() }
        declareMock<NetworkHelper>()
        mockkObject(Analytics)
        userRepo = get()
    }
    
    testGetUser()
    testGetUserId()
    testRefreshProfile()
    testFetchUser()
    testCreateUser()
    testUpdateUser()
    testUpdateFromLinkedin()
    testCreateExperience()
    testUpdateExperience()
    testDeleteExperience()
    testCreateEducation()
    testUpdateEducation()
    testDeleteEducation()
    testStartOrgVerification()
    testOrgVerification()
    testClearAppData()
    testClearDb()
    testAnalytics()
}
And it takes a lot of time to complete as mocks are created inside
beforeTest
Currently i have around 230 tests in my project and it takes around 1min to complete
@Emil Kantis will this be added in later kotest releases? If not then can you give me a headstart on how to make this custom KoinExtension?