Testy Mongo z Kotlin i KMongo

0

Hej,

Mam problem z przetestowaniem klasy, która wysyła zapytania do MongoDB z pomocą KMongo.
Testy są dla nauki także bardziej chodzi mi o przetestowanie czy idą poprawnie zapytania niż czy faktycznie coś zapisuje się w bazie.
Do mockowania używam MockK jednak zastanawiam się czy mocki to w ogóle jest droga, która powinienem obrać przy tym teście.

Problem jaki mam to to, że w momencie wywoływania testowanej metody, test staje i mieli, może dlatego, że sut oczekuje odpowiedzi a w logach widzę, że egzekucja mieli na tworzeniu nowej instancji klasy Unit.
Wykonywanie mieli na linijce val result = userApiService.insertUser(validInput)

TRACE io.mockk.proxy.jvm.ProxyMaker - Instantiating proxy for interface org.reactivestreams.Publisher via instantiator
[Test worker @coroutine#2] TRACE i.m.proxy.jvm.ObjenesisInstantiator - Skipping instantiation subsclassing class org.reactivestreams.Publisher$Subclass2 because class is not abstract.
[Test worker @coroutine#2] TRACE i.m.proxy.jvm.ObjenesisInstantiator - Creating new empty instance of class org.reactivestreams.Publisher$Subclass2
[Test worker @coroutine#2] TRACE i.m.i.i.AbstractMockFactory - Building proxy for Unit hashcode=57c956d8
[Test worker @coroutine#2] TRACE i.m.p.j.t.JvmInlineInstrumentation - Retransforming [Ljava.lang.Class;@16fb1ae8
[Test worker @coroutine#2] TRACE io.mockk.proxy.jvm.ProxyMaker - Taking instance of class kotlin.Unit itself because it is final.
[Test worker @coroutine#2] TRACE io.mockk.proxy.jvm.ProxyMaker - Instantiating proxy for class kotlin.Unit via instantiator
[Test worker @coroutine#2] TRACE i.m.proxy.jvm.ObjenesisInstantiator - Creating new empty instance of class kotlin.Unit

Jestem na etapie siedzenia nad tym kolejny dzień i zaczynam działać trochę na chybił trafił więc potrzebuje wskazówki jak to przetestować. Szukałem informacji w docsach KMongo oraz Mongo ale nie mogę pojść dalej.

Problem mam też z tym, że jeśli nie podam konkretnej implementacji dla userCollection a zamiast tego użyje mocka to dostaje błąd No answer found for CoroutineCollection.insertOne.

Dajcie też proszę znać jak w ogóle z sensownością klasy testu, bo może być tak że zabieram sie do tego od 'złej' strony :D

Dzięki!

test

class UserApiServiceTest {

    private val mongoDB = mockk<MongoDatabase>()
    private val mongoCollection = mockk<MongoCollection<User>>()
    private val kmongoDB = mockk<CoroutineDatabase>()
    private val dbProvider = mockk<DatabaseProvider>()

    private lateinit var userCollection: CoroutineCollection<User>
    private lateinit var userApiService: UserApiService

    @Before
    fun setUp() {
        every { kmongoDB.database } returns mongoDB
        every { mongoDB.getCollection("user", User::class.java) } returns mongoCollection
        userCollection = kmongoDB.getCollection()
        userApiService = UserApiServiceImpl(dbProvider)
    }

    @Test
    fun `given valid user returns True`() {
        val validInput = fakeValidUser()

        every { dbProvider.provideUserCollection() } returns userCollection
        coEvery { userCollection.insertOne(validInput).wasAcknowledged() } returns true

        runBlocking {
            val result = userApiService.insertUser(validInput)
            assertThat(result).isEqualTo(true)
        }
    }
}

testowana implementacja

class UserApiServiceImpl(
    private val databaseProvider: DatabaseProvider
) : UserApiService {

    override suspend fun insertUser(user: User): Boolean {
        return databaseProvider.provideUserCollection().insertOne(user).wasAcknowledged()
    }

    override suspend fun findUserByEmail(email: String): User? {
        return databaseProvider.provideUserCollection().findOne(User::email eq email)
    }
}

4

Osobiście bym zawrócił i użył np. test containers. Możesz tez użyć fongo (in memory Mongo). Bardziej sensownych rozwiązać jest kilka.

Od tych mockow (a chyba zamockowałeś cała bazę, co jest swoistym rekordem) i fejków bazy danych niedobrze mi się robi :)

0

@Charles_Ray: Zamokockowałem wszystko, od dołu do Mongo i pewnie masz racje choć nie ukrywam in memory chciałem właśnie ominąc i chyba widze efekt :D
Czytałem dziś dziś o testcontainers, fongo znam więc zaoram to i spróbuje innego sposobu, dziękuje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1