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