Refactor Notification System
Add Tests for notification system
This commit is contained in:
@@ -31,7 +31,7 @@ import org.koin.test.AutoCloseKoinTest
|
||||
import org.koin.test.KoinTest
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class EventNotificationTest : KoinTest, AutoCloseKoinTest() {
|
||||
class EventNotificationTest {
|
||||
@InternalCoroutinesApi
|
||||
@KtorExperimentalLocationsAPI
|
||||
@KtorExperimentalAPI
|
||||
@@ -43,9 +43,12 @@ class EventNotificationTest : KoinTest, AutoCloseKoinTest() {
|
||||
val emailSender = mockk<NotificationEmailSender>() {
|
||||
every { sendEmail(any()) } returns Unit
|
||||
}
|
||||
val redisClient = spyk<RedisAsyncCommands<String, String>> {
|
||||
RedisClient.create(Configuration.redis).connect().async() ?: error("Unable to connect to redis")
|
||||
}
|
||||
|
||||
/* Init Spy on redis client */
|
||||
val redisClient = spyk<RedisClient>(RedisClient.create(Configuration.redis))
|
||||
val asyncCommand = spyk(redisClient.connect().async())
|
||||
every { redisClient.connect().async() } returns asyncCommand
|
||||
|
||||
val rabbitFactory: ConnectionFactory = spyk {
|
||||
ConnectionFactory().apply { setUri(Configuration.rabbitmq) }
|
||||
}
|
||||
@@ -67,7 +70,7 @@ class EventNotificationTest : KoinTest, AutoCloseKoinTest() {
|
||||
/* Config consumer */
|
||||
EventNotification(
|
||||
rabbitFactory = rabbitFactory,
|
||||
redis = redisClient,
|
||||
redisClient = redisClient,
|
||||
followArticleRepo = followArticleRepo,
|
||||
followConstitutionRepo = mockk(),
|
||||
notificationEmailSender = emailSender,
|
||||
@@ -90,12 +93,9 @@ class EventNotificationTest : KoinTest, AutoCloseKoinTest() {
|
||||
)
|
||||
).await()
|
||||
|
||||
/* Wait to receive message */
|
||||
delay(1000)
|
||||
|
||||
/* Check if notifications sent */
|
||||
verify { followArticleRepo.findFollowsByTarget(any()) }
|
||||
verify { emailSender.sendEmail(any()) }
|
||||
verify { redisClient.zadd(any<String>(), any<Double>(), any<String>()) }
|
||||
verify(timeout = 1000) { followArticleRepo.findFollowsByTarget(any()) }
|
||||
verify(timeout = 1000) { emailSender.sendEmail(any()) }
|
||||
verify(timeout = 1000) { asyncCommand.zadd(any<String>(), any<Double>(), any<String>()) }
|
||||
}
|
||||
}
|
||||
|
||||
89
src/test/kotlin/functional/NotificationsPushTest.kt
Normal file
89
src/test/kotlin/functional/NotificationsPushTest.kt
Normal file
@@ -0,0 +1,89 @@
|
||||
package functional
|
||||
|
||||
import fr.dcproject.application.Configuration
|
||||
import fr.dcproject.component.article.ArticleForView
|
||||
import fr.dcproject.component.citizen.CitizenRef
|
||||
import fr.dcproject.notification.ArticleUpdateNotification
|
||||
import fr.dcproject.notification.Notification
|
||||
import io.lettuce.core.Limit
|
||||
import io.lettuce.core.RedisClient
|
||||
import io.mockk.every
|
||||
import io.mockk.spyk
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import notification.NotificationsPush
|
||||
import org.amshove.kluent.`should be equal to`
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.koin.test.AutoCloseKoinTest
|
||||
import org.koin.test.KoinTest
|
||||
|
||||
internal class NotificationsPushTest {
|
||||
@Test
|
||||
@Tag("functional")
|
||||
fun `Notification from redis is well catch and return`() = runBlocking {
|
||||
/* Redis client for test */
|
||||
val redisClientTest = RedisClient.create(Configuration.redis)
|
||||
|
||||
/* Init Spy on redis client */
|
||||
val redisClient = spyk<RedisClient>(RedisClient.create(Configuration.redis))
|
||||
val asyncCommand = spyk(redisClient.connect().async())
|
||||
every { redisClient.connect().async() } returns asyncCommand
|
||||
|
||||
/* Citizen of notification */
|
||||
val citizen = CitizenRef()
|
||||
/* Article is the target of the notification */
|
||||
val article = ArticleForView(
|
||||
content = "content..",
|
||||
createdBy = citizen,
|
||||
description = "desc",
|
||||
title = "Super Title",
|
||||
)
|
||||
/* Init two notification, one called before subscription, and the other after */
|
||||
val notifBeforeSubscribe = ArticleUpdateNotification(article)
|
||||
val notifAfterSubscribe = ArticleUpdateNotification(article)
|
||||
|
||||
/* init event for emulate incomint message from websocket */
|
||||
val event = MutableSharedFlow<Notification>()
|
||||
val incomingFlow = event.asSharedFlow()
|
||||
|
||||
spyk(object { var counter = 0}).run { /* Counter for count the callback of notification */
|
||||
/* Sent notification */
|
||||
redisClientTest.connect().sync().run {
|
||||
zadd(
|
||||
"notification:${citizen.id}",
|
||||
notifBeforeSubscribe.id,
|
||||
notifBeforeSubscribe.toString()
|
||||
)
|
||||
}
|
||||
|
||||
/* Init NotificationPush system, and set assertion in callback */
|
||||
NotificationsPush(redisClient, citizen, incomingFlow) {
|
||||
counter++
|
||||
if (counter == 1) it.id `should be equal to` notifBeforeSubscribe.id
|
||||
else it.id `should be equal to` notifAfterSubscribe.id
|
||||
}
|
||||
|
||||
/* Sent the notification */
|
||||
redisClientTest.connect().sync().run {
|
||||
zadd(
|
||||
"notification:${citizen.id}",
|
||||
notifAfterSubscribe.id,
|
||||
notifAfterSubscribe.toString()
|
||||
)
|
||||
}
|
||||
|
||||
/* Verify if the callback is called 2 times */
|
||||
verify(exactly = 4, timeout = 200) { counter }
|
||||
assertEquals(2, counter, "The notification must be call 2 times")
|
||||
|
||||
/* Emit an event to delete notification */
|
||||
event.emit(notifAfterSubscribe)
|
||||
/* Verify the "mark as read" is called */
|
||||
verify(timeout = 300) { asyncCommand.zremrangebyscore(any(), any()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user