From e4f290a5bad84ccd0febcd4e71ad3cc00e3a3687 Mon Sep 17 00:00:00 2001 From: Anders Rognstad <79838644+andersrognstad@users.noreply.github.com> Date: Tue, 24 Sep 2024 13:37:04 +0200 Subject: [PATCH] IS-2685: Publish forhandsvarsel to esyfovarsel (#27) --- src/main/kotlin/no/nav/syfo/App.kt | 23 +++- .../nav/syfo/application/IVarselProducer.kt | 13 ++ .../nav/syfo/application/IVarselRepository.kt | 11 ++ .../no/nav/syfo/application/VarselService.kt | 24 ++++ .../infrastructure/cronjob/CronjobModule.kt | 5 + .../cronjob/PublishForhandsvarselCronjob.kt | 10 ++ .../database/repository/VarselRepository.kt | 64 ++++++++++ .../repository/VurderingRepository.kt | 11 -- .../infrastructure/kafka/VarselProducer.kt | 23 ++++ .../EsyfoVarselHendelseSerializer.kt | 11 ++ .../EsyfovarselHendelseProducer.kt | 26 ++-- .../nav/syfo/application/VarselServiceSpek.kt | 119 ++++++++++++++++++ 12 files changed, 314 insertions(+), 26 deletions(-) create mode 100644 src/main/kotlin/no/nav/syfo/application/IVarselProducer.kt create mode 100644 src/main/kotlin/no/nav/syfo/application/IVarselRepository.kt create mode 100644 src/main/kotlin/no/nav/syfo/application/VarselService.kt create mode 100644 src/main/kotlin/no/nav/syfo/infrastructure/cronjob/PublishForhandsvarselCronjob.kt create mode 100644 src/main/kotlin/no/nav/syfo/infrastructure/database/repository/VarselRepository.kt create mode 100644 src/main/kotlin/no/nav/syfo/infrastructure/kafka/VarselProducer.kt create mode 100644 src/main/kotlin/no/nav/syfo/infrastructure/kafka/esyfovarsel/EsyfoVarselHendelseSerializer.kt create mode 100644 src/test/kotlin/no/nav/syfo/application/VarselServiceSpek.kt diff --git a/src/main/kotlin/no/nav/syfo/App.kt b/src/main/kotlin/no/nav/syfo/App.kt index 06f1a94..c830023 100644 --- a/src/main/kotlin/no/nav/syfo/App.kt +++ b/src/main/kotlin/no/nav/syfo/App.kt @@ -6,6 +6,7 @@ import io.ktor.server.config.* import io.ktor.server.engine.* import io.ktor.server.netty.* import no.nav.syfo.api.apiModule +import no.nav.syfo.application.VarselService import no.nav.syfo.application.VurderingService import no.nav.syfo.infrastructure.clients.azuread.AzureAdClient import no.nav.syfo.infrastructure.clients.dokarkiv.DokarkivClient @@ -17,10 +18,14 @@ import no.nav.syfo.infrastructure.clients.wellknown.getWellKnown import no.nav.syfo.infrastructure.cronjob.launchCronjobs import no.nav.syfo.infrastructure.database.applicationDatabase import no.nav.syfo.infrastructure.database.databaseModule +import no.nav.syfo.infrastructure.database.repository.VarselRepository import no.nav.syfo.infrastructure.database.repository.VurderingRepository import no.nav.syfo.infrastructure.journalforing.JournalforingService +import no.nav.syfo.infrastructure.kafka.VarselProducer import no.nav.syfo.infrastructure.kafka.VurderingProducer import no.nav.syfo.infrastructure.kafka.VurderingRecordSerializer +import no.nav.syfo.infrastructure.kafka.esyfovarsel.EsyfoVarselHendelseSerializer +import no.nav.syfo.infrastructure.kafka.esyfovarsel.EsyfovarselHendelseProducer import no.nav.syfo.infrastructure.kafka.kafkaAivenProducerConfig import org.apache.kafka.clients.producer.KafkaProducer import org.slf4j.LoggerFactory @@ -54,7 +59,11 @@ fun main() { val pdfGenClient = PdfGenClient( pdfGenBaseUrl = environment.clients.ispdfgen.baseUrl, ) - + val arbeidstakerForhandsvarselProducer = EsyfovarselHendelseProducer( + producer = KafkaProducer( + kafkaAivenProducerConfig(kafkaEnvironment = environment.kafka) + ) + ) val vurderingProducer = VurderingProducer( producer = KafkaProducer(kafkaAivenProducerConfig(kafkaEnvironment = environment.kafka)) ) @@ -68,8 +77,8 @@ fun main() { pdlClient = pdlClient, ) - lateinit var vurderingRepository: VurderingRepository lateinit var vurderingService: VurderingService + lateinit var varselService: VarselService val applicationEngineEnvironment = applicationEngineEnvironment { @@ -83,9 +92,10 @@ fun main() { databaseEnvironment = environment.database, ) - vurderingRepository = VurderingRepository( + val vurderingRepository = VurderingRepository( database = applicationDatabase, ) + val varselRepository = VarselRepository(database = applicationDatabase) vurderingService = VurderingService( journalforingService = journalforingService, @@ -93,6 +103,12 @@ fun main() { vurderingProducer = vurderingProducer, vurderingPdfService = vurderingPdfService, ) + varselService = VarselService( + varselRepository = varselRepository, + varselProducer = VarselProducer( + arbeidstakerForhandsvarselProducer = arbeidstakerForhandsvarselProducer, + ), + ) apiModule( applicationState = applicationState, @@ -113,6 +129,7 @@ fun main() { applicationState = applicationState, environment = environment, vurderingService = vurderingService, + varselService = varselService, ) } diff --git a/src/main/kotlin/no/nav/syfo/application/IVarselProducer.kt b/src/main/kotlin/no/nav/syfo/application/IVarselProducer.kt new file mode 100644 index 0000000..5720f79 --- /dev/null +++ b/src/main/kotlin/no/nav/syfo/application/IVarselProducer.kt @@ -0,0 +1,13 @@ +package no.nav.syfo.application + +import no.nav.syfo.domain.JournalpostId +import no.nav.syfo.domain.Personident +import no.nav.syfo.domain.Varsel + +interface IVarselProducer { + fun sendArbeidstakerForhandsvarsel( + personIdent: Personident, + journalpostId: JournalpostId, + varsel: Varsel + ): Result +} diff --git a/src/main/kotlin/no/nav/syfo/application/IVarselRepository.kt b/src/main/kotlin/no/nav/syfo/application/IVarselRepository.kt new file mode 100644 index 0000000..d9ebac1 --- /dev/null +++ b/src/main/kotlin/no/nav/syfo/application/IVarselRepository.kt @@ -0,0 +1,11 @@ +package no.nav.syfo.application + +import no.nav.syfo.domain.JournalpostId +import no.nav.syfo.domain.Personident +import no.nav.syfo.domain.Varsel +import java.util.* + +interface IVarselRepository { + fun getUnpublishedVarsler(): List> + fun updatePublishedAt(varselUuid: UUID) +} diff --git a/src/main/kotlin/no/nav/syfo/application/VarselService.kt b/src/main/kotlin/no/nav/syfo/application/VarselService.kt new file mode 100644 index 0000000..ce6acdb --- /dev/null +++ b/src/main/kotlin/no/nav/syfo/application/VarselService.kt @@ -0,0 +1,24 @@ +package no.nav.syfo.application + +import no.nav.syfo.domain.Varsel + +class VarselService( + private val varselRepository: IVarselRepository, + private val varselProducer: IVarselProducer +) { + + fun publishUnpublishedVarsler(): List> { + val unpublishedVarsler = varselRepository.getUnpublishedVarsler() + + return unpublishedVarsler.map { (personident, journalpostId, varsel) -> + varselProducer.sendArbeidstakerForhandsvarsel( + personIdent = personident, + journalpostId = journalpostId, + varsel = varsel, + ).map { + varselRepository.updatePublishedAt(it.uuid) + it + } + } + } +} diff --git a/src/main/kotlin/no/nav/syfo/infrastructure/cronjob/CronjobModule.kt b/src/main/kotlin/no/nav/syfo/infrastructure/cronjob/CronjobModule.kt index 75bfe3b..22ab5a8 100644 --- a/src/main/kotlin/no/nav/syfo/infrastructure/cronjob/CronjobModule.kt +++ b/src/main/kotlin/no/nav/syfo/infrastructure/cronjob/CronjobModule.kt @@ -2,6 +2,7 @@ package no.nav.syfo.infrastructure.cronjob import no.nav.syfo.ApplicationState import no.nav.syfo.Environment +import no.nav.syfo.application.VarselService import no.nav.syfo.application.VurderingService import no.nav.syfo.infrastructure.clients.leaderelection.LeaderPodClient import no.nav.syfo.launchBackgroundTask @@ -10,6 +11,7 @@ fun launchCronjobs( applicationState: ApplicationState, environment: Environment, vurderingService: VurderingService, + varselService: VarselService, ) { val leaderPodClient = LeaderPodClient( electorPath = environment.electorPath @@ -20,6 +22,9 @@ fun launchCronjobs( ) val cronjobs = mutableListOf() + val publishForhandsvarselCronjob = PublishForhandsvarselCronjob(varselService = varselService) + cronjobs.add(publishForhandsvarselCronjob) + val journalforVurderingerCronjob = JournalforVurderingerCronjob(vurderingService) cronjobs.add(journalforVurderingerCronjob) diff --git a/src/main/kotlin/no/nav/syfo/infrastructure/cronjob/PublishForhandsvarselCronjob.kt b/src/main/kotlin/no/nav/syfo/infrastructure/cronjob/PublishForhandsvarselCronjob.kt new file mode 100644 index 0000000..bae7e56 --- /dev/null +++ b/src/main/kotlin/no/nav/syfo/infrastructure/cronjob/PublishForhandsvarselCronjob.kt @@ -0,0 +1,10 @@ +package no.nav.syfo.infrastructure.cronjob + +import no.nav.syfo.application.VarselService + +class PublishForhandsvarselCronjob(private val varselService: VarselService) : Cronjob { + override val initialDelayMinutes: Long = 4 + override val intervalDelayMinutes: Long = 10 + + override suspend fun run() = varselService.publishUnpublishedVarsler() +} diff --git a/src/main/kotlin/no/nav/syfo/infrastructure/database/repository/VarselRepository.kt b/src/main/kotlin/no/nav/syfo/infrastructure/database/repository/VarselRepository.kt new file mode 100644 index 0000000..f283613 --- /dev/null +++ b/src/main/kotlin/no/nav/syfo/infrastructure/database/repository/VarselRepository.kt @@ -0,0 +1,64 @@ +package no.nav.syfo.infrastructure.database.repository + +import no.nav.syfo.application.IVarselRepository +import no.nav.syfo.domain.JournalpostId +import no.nav.syfo.domain.Personident +import no.nav.syfo.domain.Varsel +import no.nav.syfo.infrastructure.database.DatabaseInterface +import no.nav.syfo.infrastructure.database.toList +import no.nav.syfo.util.nowUTC +import java.sql.ResultSet +import java.sql.SQLException +import java.time.OffsetDateTime +import java.util.* + +class VarselRepository(private val database: DatabaseInterface) : IVarselRepository { + + override fun getUnpublishedVarsler(): List> = database.connection.use { connection -> + connection.prepareStatement(GET_UNPUBLISHED_VARSEL).use { + it.executeQuery().toList { Triple(Personident(getString("personident")), JournalpostId(getString("journalpost_id")), toPVarsel()) } + } + }.map { (personident, journalpostId, pVarsel) -> Triple(personident, journalpostId, pVarsel.toVarsel()) } + + override fun updatePublishedAt(varselUuid: UUID) = + database.connection.use { connection -> + connection.prepareStatement(UPDATE_PUBLISHED_AT).use { + it.setObject(1, nowUTC()) + it.setObject(2, nowUTC()) + it.setString(3, varselUuid.toString()) + val updated = it.executeUpdate() + if (updated != 1) { + throw SQLException("Expected a single row to be updated, got update count $updated") + } + } + connection.commit() + } + + companion object { + private const val GET_UNPUBLISHED_VARSEL = + """ + SELECT vu.personident, vu.journalpost_id, v.* FROM varsel v + INNER JOIN vurdering vu + ON v.vurdering_id = vu.id + WHERE vu.journalpost_id IS NOT NULL AND v.published_at IS NULL + """ + + private const val UPDATE_PUBLISHED_AT = + """ + UPDATE varsel + SET published_at = ?, updated_at = ? + WHERE uuid = ? + """ + } +} + +internal fun ResultSet.toPVarsel(): PVarsel = + PVarsel( + id = getInt("id"), + uuid = UUID.fromString(getString("uuid")), + vurderingId = getInt("vurdering_id"), + createdAt = getObject("created_at", OffsetDateTime::class.java), + updatedAt = getObject("updated_at", OffsetDateTime::class.java), + svarfrist = getDate("svarfrist").toLocalDate(), + publishedAt = getObject("published_at", OffsetDateTime::class.java), + ) diff --git a/src/main/kotlin/no/nav/syfo/infrastructure/database/repository/VurderingRepository.kt b/src/main/kotlin/no/nav/syfo/infrastructure/database/repository/VurderingRepository.kt index 9b4bf77..8b68605 100644 --- a/src/main/kotlin/no/nav/syfo/infrastructure/database/repository/VurderingRepository.kt +++ b/src/main/kotlin/no/nav/syfo/infrastructure/database/repository/VurderingRepository.kt @@ -294,17 +294,6 @@ internal fun ResultSet.toPVurdering(): PVurdering = publishedAt = getObject("published_at", OffsetDateTime::class.java), ) -private fun ResultSet.toPVarsel(): PVarsel = - PVarsel( - id = getInt("id"), - uuid = UUID.fromString(getString("uuid")), - vurderingId = getInt("vurdering_id"), - createdAt = getObject("created_at", OffsetDateTime::class.java), - updatedAt = getObject("updated_at", OffsetDateTime::class.java), - svarfrist = getDate("svarfrist").toLocalDate(), - publishedAt = getObject("published_at", OffsetDateTime::class.java), - ) - fun ResultSet.toPVurderingPdf(): PVurderingPdf = PVurderingPdf( id = getInt("id"), diff --git a/src/main/kotlin/no/nav/syfo/infrastructure/kafka/VarselProducer.kt b/src/main/kotlin/no/nav/syfo/infrastructure/kafka/VarselProducer.kt new file mode 100644 index 0000000..403cf44 --- /dev/null +++ b/src/main/kotlin/no/nav/syfo/infrastructure/kafka/VarselProducer.kt @@ -0,0 +1,23 @@ +package no.nav.syfo.infrastructure.kafka + +import no.nav.syfo.application.IVarselProducer +import no.nav.syfo.domain.JournalpostId +import no.nav.syfo.domain.Personident +import no.nav.syfo.domain.Varsel +import no.nav.syfo.infrastructure.kafka.esyfovarsel.EsyfovarselHendelseProducer + +class VarselProducer( + private val arbeidstakerForhandsvarselProducer: EsyfovarselHendelseProducer, +) : IVarselProducer { + + override fun sendArbeidstakerForhandsvarsel( + personIdent: Personident, + journalpostId: JournalpostId, + varsel: Varsel + ): Result = + arbeidstakerForhandsvarselProducer.sendArbeidstakerForhandsvarsel( + personIdent = personIdent, + journalpostId = journalpostId, + varsel = varsel + ) +} diff --git a/src/main/kotlin/no/nav/syfo/infrastructure/kafka/esyfovarsel/EsyfoVarselHendelseSerializer.kt b/src/main/kotlin/no/nav/syfo/infrastructure/kafka/esyfovarsel/EsyfoVarselHendelseSerializer.kt new file mode 100644 index 0000000..a399989 --- /dev/null +++ b/src/main/kotlin/no/nav/syfo/infrastructure/kafka/esyfovarsel/EsyfoVarselHendelseSerializer.kt @@ -0,0 +1,11 @@ +package no.nav.syfo.infrastructure.kafka.esyfovarsel + +import no.nav.syfo.infrastructure.kafka.esyfovarsel.dto.EsyfovarselHendelse +import no.nav.syfo.util.configuredJacksonMapper +import org.apache.kafka.common.serialization.Serializer + +class EsyfoVarselHendelseSerializer : Serializer { + private val mapper = configuredJacksonMapper() + override fun serialize(topic: String?, data: EsyfovarselHendelse?): ByteArray = + mapper.writeValueAsBytes(data) +} diff --git a/src/main/kotlin/no/nav/syfo/infrastructure/kafka/esyfovarsel/EsyfovarselHendelseProducer.kt b/src/main/kotlin/no/nav/syfo/infrastructure/kafka/esyfovarsel/EsyfovarselHendelseProducer.kt index 1aa2f35..3291e52 100644 --- a/src/main/kotlin/no/nav/syfo/infrastructure/kafka/esyfovarsel/EsyfovarselHendelseProducer.kt +++ b/src/main/kotlin/no/nav/syfo/infrastructure/kafka/esyfovarsel/EsyfovarselHendelseProducer.kt @@ -1,6 +1,8 @@ package no.nav.syfo.infrastructure.kafka.esyfovarsel -import no.nav.syfo.domain.ManglendeMedvirkningVurdering +import no.nav.syfo.domain.JournalpostId +import no.nav.syfo.domain.Personident +import no.nav.syfo.domain.Varsel import no.nav.syfo.infrastructure.kafka.esyfovarsel.dto.ArbeidstakerHendelse import no.nav.syfo.infrastructure.kafka.esyfovarsel.dto.EsyfovarselHendelse import no.nav.syfo.infrastructure.kafka.esyfovarsel.dto.HendelseType @@ -14,18 +16,18 @@ import java.util.* class EsyfovarselHendelseProducer( private val producer: KafkaProducer, ) { - - fun sendVurderingVarsel(vurdering: ManglendeMedvirkningVurdering): Result { - if (vurdering.journalpostId == null) - throw IllegalStateException("JournalpostId is null for vurdering ${vurdering.uuid}") - + fun sendArbeidstakerForhandsvarsel( + personIdent: Personident, + journalpostId: JournalpostId, + varsel: Varsel + ): Result { val varselHendelse = ArbeidstakerHendelse( type = HendelseType.SM_FORHANDSVARSEL_MANGLENDE_MEDVIRKNING, - arbeidstakerFnr = vurdering.personident.value, + arbeidstakerFnr = personIdent.value, data = VarselData( journalpost = VarselDataJournalpost( - uuid = vurdering.uuid.toString(), - id = vurdering.journalpostId!!.value, + uuid = varsel.uuid.toString(), + id = journalpostId.value, ), ), orgnummer = null, @@ -35,13 +37,13 @@ class EsyfovarselHendelseProducer( producer.send( ProducerRecord( ESYFOVARSEL_TOPIC, - UUID.nameUUIDFromBytes(vurdering.personident.value.toByteArray()).toString(), + UUID.randomUUID().toString(), varselHendelse, ) ).get() - Result.success(vurdering) + Result.success(varsel) } catch (e: Exception) { - log.error("Exception was thrown when attempting to send hendelse varsel (uuid: ${vurdering.uuid}) to esyfovarsel: ${e.message}") + log.error("Exception was thrown when attempting to send hendelse varsel (uuid: ${varsel.uuid}) to esyfovarsel: ${e.message}") Result.failure(e) } } diff --git a/src/test/kotlin/no/nav/syfo/application/VarselServiceSpek.kt b/src/test/kotlin/no/nav/syfo/application/VarselServiceSpek.kt new file mode 100644 index 0000000..98055cd --- /dev/null +++ b/src/test/kotlin/no/nav/syfo/application/VarselServiceSpek.kt @@ -0,0 +1,119 @@ +package no.nav.syfo.application + +import io.mockk.* +import no.nav.syfo.ExternalMockEnvironment +import no.nav.syfo.UserConstants +import no.nav.syfo.domain.JournalpostId +import no.nav.syfo.domain.ManglendeMedvirkningVurdering +import no.nav.syfo.domain.Varsel +import no.nav.syfo.domain.VurderingType +import no.nav.syfo.generator.generateVurdering +import no.nav.syfo.infrastructure.database.dropData +import no.nav.syfo.infrastructure.database.repository.VarselRepository +import no.nav.syfo.infrastructure.database.repository.VurderingRepository +import no.nav.syfo.infrastructure.kafka.esyfovarsel.EsyfovarselHendelseProducer +import no.nav.syfo.infrastructure.kafka.esyfovarsel.dto.ArbeidstakerHendelse +import no.nav.syfo.infrastructure.kafka.esyfovarsel.dto.EsyfovarselHendelse +import no.nav.syfo.infrastructure.kafka.esyfovarsel.dto.HendelseType +import no.nav.syfo.infrastructure.kafka.esyfovarsel.dto.VarselData +import org.amshove.kluent.shouldBeEmpty +import org.amshove.kluent.shouldBeEqualTo +import org.apache.kafka.clients.producer.KafkaProducer +import org.apache.kafka.clients.producer.ProducerRecord +import org.apache.kafka.clients.producer.RecordMetadata +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe +import java.util.concurrent.Future + +private val journalpostId = JournalpostId("123") + +class VarselServiceSpek : Spek({ + describe(VarselService::class.java.simpleName) { + + val externalMockEnvironment = ExternalMockEnvironment.instance + val database = externalMockEnvironment.database + + val varselRepository = VarselRepository(database = database) + val vurderingRepository = VurderingRepository(database = database) + val mockEsyfoVarselHendelseProducer = mockk>() + val arbeidstakerForhandsvarselProducer = EsyfovarselHendelseProducer(producer = mockEsyfoVarselHendelseProducer) + val varselProducer = no.nav.syfo.infrastructure.kafka.VarselProducer( + arbeidstakerForhandsvarselProducer = arbeidstakerForhandsvarselProducer, + ) + val varselService = VarselService( + varselRepository = varselRepository, + varselProducer = varselProducer, + ) + + beforeEachTest { + clearAllMocks() + coEvery { mockEsyfoVarselHendelseProducer.send(any()) } returns mockk>(relaxed = true) + } + afterEachTest { + database.dropData() + } + + val vurderingForhandsvarsel = generateVurdering( + type = VurderingType.FORHANDSVARSEL, + ) as ManglendeMedvirkningVurdering.Forhandsvarsel + + fun createUnpublishedVarsel(): Varsel { + vurderingRepository.saveManglendeMedvirkningVurdering( + vurdering = vurderingForhandsvarsel, + vurderingPdf = UserConstants.PDF_FORHANDSVARSEL, + ) + val unpublishedVarsel = vurderingForhandsvarsel.varsel + vurderingRepository.setJournalpostId(vurderingForhandsvarsel.copy(journalpostId = journalpostId)) + + return unpublishedVarsel + } + + describe("publishUnpublishedVarsler") { + + it("publishes unpublished varsel") { + val unpublishedVarsel = createUnpublishedVarsel() + + val (success, failed) = varselService.publishUnpublishedVarsler().partition { it.isSuccess } + failed.size shouldBeEqualTo 0 + success.size shouldBeEqualTo 1 + + val producerRecordSlot = slot>() + verify(exactly = 1) { mockEsyfoVarselHendelseProducer.send(capture(producerRecordSlot)) } + + val publishedVarsel = success.first().getOrThrow() + publishedVarsel.uuid.shouldBeEqualTo(unpublishedVarsel.uuid) + + varselRepository.getUnpublishedVarsler().shouldBeEmpty() + + val esyfovarselHendelse = producerRecordSlot.captured.value() as ArbeidstakerHendelse + esyfovarselHendelse.type.shouldBeEqualTo(HendelseType.SM_FORHANDSVARSEL_MANGLENDE_MEDVIRKNING) + esyfovarselHendelse.arbeidstakerFnr.shouldBeEqualTo(UserConstants.ARBEIDSTAKER_PERSONIDENT.value) + val varselData = esyfovarselHendelse.data as VarselData + varselData.journalpost?.uuid.shouldBeEqualTo(publishedVarsel.uuid.toString()) + varselData.journalpost?.id!!.shouldBeEqualTo(journalpostId.value) + } + + it("publishes nothing when no unpublished varsel") { + val (success, failed) = varselService.publishUnpublishedVarsler().partition { it.isSuccess } + failed.size shouldBeEqualTo 0 + success.size shouldBeEqualTo 0 + + verify(exactly = 0) { mockEsyfoVarselHendelseProducer.send(any()) } + } + + it("fails publishing when kafka-producer fails") { + val unpublishedVarsel = createUnpublishedVarsel() + every { mockEsyfoVarselHendelseProducer.send(any()) } throws Exception("Error producing to kafka") + + val (success, failed) = varselService.publishUnpublishedVarsler().partition { it.isSuccess } + failed.size shouldBeEqualTo 1 + success.size shouldBeEqualTo 0 + + verify(exactly = 1) { mockEsyfoVarselHendelseProducer.send(any()) } + + val (_, _, varsel) = varselRepository.getUnpublishedVarsler().first() + varsel.uuid.shouldBeEqualTo(unpublishedVarsel.uuid) + } + } + } +})