Skip to content

Commit c382e20

Browse files
committed
La til tester for v2 api
1 parent 6a066e9 commit c382e20

File tree

6 files changed

+307
-122
lines changed

6 files changed

+307
-122
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package no.nav.paw.arbeidssokerregisteret
2+
3+
import io.kotest.core.spec.style.FreeSpec
4+
import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder
5+
import io.kotest.matchers.collections.shouldNotBeEmpty
6+
import io.kotest.matchers.nulls.shouldBeNull
7+
import io.kotest.matchers.nulls.shouldNotBeNull
8+
import io.kotest.matchers.should
9+
import io.kotest.matchers.shouldBe
10+
import io.ktor.client.call.*
11+
import io.ktor.server.auth.*
12+
import io.ktor.server.testing.*
13+
import io.mockk.mockk
14+
import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil
15+
import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.FeilV2
16+
import no.nav.paw.arbeidssokerregisteret.auth.configureAuthentication
17+
import no.nav.paw.arbeidssokerregisteret.plugins.configureHTTP
18+
import no.nav.paw.arbeidssokerregisteret.plugins.configureSerialization
19+
import no.nav.paw.arbeidssokerregisteret.routes.arbeidssokerRoutes
20+
import no.nav.paw.arbeidssokerregisteret.routes.arbeidssokerRoutesV2
21+
import no.nav.paw.arbeidssokerregisteret.testdata.TestCase
22+
import no.nav.paw.arbeidssokerregisteret.testdata.TestCaseBuilder
23+
import no.nav.security.mock.oauth2.MockOAuth2Server
24+
import org.slf4j.LoggerFactory
25+
26+
27+
class ApiV1TestCaseRunner : FreeSpec({
28+
val mockOAuthServer = MockOAuth2Server()
29+
beforeSpec {
30+
mockOAuthServer.start()
31+
}
32+
afterSpec {
33+
mockOAuthServer.shutdown()
34+
}
35+
val testCases = TestCase::class.sealedSubclasses
36+
"Verifiserer oppsett av test caser" - {
37+
"Det må finnes minst en test" {
38+
testCases.shouldNotBeEmpty()
39+
}
40+
"Alle tester må ha 'objectInstance" - {
41+
testCases.forEach { case ->
42+
"${case.simpleName} må ha 'objectInstance'" {
43+
case.objectInstance.shouldNotBeNull()
44+
}
45+
}
46+
}
47+
}
48+
"Test cases V1" - {
49+
TestCase::class.sealedSubclasses
50+
.mapNotNull { it.objectInstance }
51+
.forEach { testCase ->
52+
val logger = LoggerFactory.getLogger(testCase::class.java)
53+
"Test ${testCase::class.simpleName?.readable()}" - {
54+
"Verifiser API V1" - {
55+
with(initTestCaseContext()) {
56+
"Verifiser API response" {
57+
testApplication {
58+
application {
59+
configureSerialization()
60+
configureHTTP()
61+
configureAuthentication(mockOAuthServer)
62+
}
63+
routing {
64+
authenticate("tokenx", "azure") {
65+
arbeidssokerRoutes(startStoppRequestHandler, mockk())
66+
arbeidssokerRoutesV2(startStoppRequestHandler)
67+
}
68+
}
69+
val client = createClient { defaultConfig() }
70+
val id = testCase.id
71+
val person = testCase.person
72+
logger.info("Running test for $id")
73+
personInfoService.setPersonInfo(id, person)
74+
val testConfiguration = TestCaseBuilder(mockOAuthServer, autorisasjonService)
75+
.also { testCase.configure(it) }
76+
val status =
77+
client.startPeriode(
78+
id,
79+
testConfiguration.authToken,
80+
testCase.forhaandsGodkjent
81+
)
82+
status.status shouldBe testCase.producesHttpResponse
83+
testCase.producesError?.also { expectedErrorResponse ->
84+
val body = status.body<Feil>()
85+
body.feilKode.name shouldBe expectedErrorResponse.feilKode.name
86+
body.melding shouldBe expectedErrorResponse.melding
87+
body.aarsakTilAvvisning?.regel shouldBe expectedErrorResponse.aarsakTilAvvisning?.regel
88+
expectedErrorResponse.aarsakTilAvvisning?.detaljer?.also { expectedDetails ->
89+
body.aarsakTilAvvisning?.detaljer.shouldNotBeNull()
90+
body.aarsakTilAvvisning?.detaljer?.shouldContainExactlyInAnyOrder(
91+
expectedDetails
92+
)
93+
}
94+
}
95+
}
96+
}
97+
"Verifiser Kafka melding" {
98+
val expectedRecord = testCase.producesRecord(kafkaKeys)
99+
if (expectedRecord != null) {
100+
verify(
101+
actual = producer.next(),
102+
expected = expectedRecord
103+
)
104+
producer.next().shouldBeNull()
105+
} else {
106+
producer.next().shouldBeNull()
107+
}
108+
}
109+
}
110+
}
111+
}
112+
}
113+
}
114+
})
115+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package no.nav.paw.arbeidssokerregisteret
2+
3+
import io.kotest.core.spec.style.FreeSpec
4+
import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder
5+
import io.kotest.matchers.collections.shouldNotBeEmpty
6+
import io.kotest.matchers.nulls.shouldBeNull
7+
import io.kotest.matchers.nulls.shouldNotBeNull
8+
import io.kotest.matchers.should
9+
import io.kotest.matchers.shouldBe
10+
import io.ktor.client.call.*
11+
import io.ktor.server.auth.*
12+
import io.ktor.server.testing.*
13+
import io.mockk.mockk
14+
import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil
15+
import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.FeilV2
16+
import no.nav.paw.arbeidssokerregisteret.auth.configureAuthentication
17+
import no.nav.paw.arbeidssokerregisteret.plugins.configureHTTP
18+
import no.nav.paw.arbeidssokerregisteret.plugins.configureSerialization
19+
import no.nav.paw.arbeidssokerregisteret.routes.arbeidssokerRoutes
20+
import no.nav.paw.arbeidssokerregisteret.routes.arbeidssokerRoutesV2
21+
import no.nav.paw.arbeidssokerregisteret.testdata.TestCase
22+
import no.nav.paw.arbeidssokerregisteret.testdata.TestCaseBuilder
23+
import no.nav.security.mock.oauth2.MockOAuth2Server
24+
import org.slf4j.LoggerFactory
25+
26+
27+
class ApiV2TestCaseRunner : FreeSpec({
28+
val mockOAuthServer = MockOAuth2Server()
29+
beforeSpec {
30+
mockOAuthServer.start()
31+
}
32+
afterSpec {
33+
mockOAuthServer.shutdown()
34+
}
35+
val testCases = TestCase::class.sealedSubclasses
36+
"Verifiserer oppsett av test caser" - {
37+
"Det må finnes minst en test" {
38+
testCases.shouldNotBeEmpty()
39+
}
40+
"Alle tester må ha 'objectInstance" - {
41+
testCases.forEach { case ->
42+
"${case.simpleName} må ha 'objectInstance'" {
43+
case.objectInstance.shouldNotBeNull()
44+
}
45+
}
46+
}
47+
}
48+
"Test cases V2" - {
49+
TestCase::class.sealedSubclasses
50+
.mapNotNull { it.objectInstance }
51+
.forEach { testCase ->
52+
val logger = LoggerFactory.getLogger(testCase::class.java)
53+
"Test API V2 ${testCase::class.simpleName?.readable()}" - {
54+
"Verifiser API V2" - {
55+
with(initTestCaseContext()) {
56+
"Verifiser API response" {
57+
testApplication {
58+
application {
59+
configureSerialization()
60+
configureHTTP()
61+
configureAuthentication(mockOAuthServer)
62+
}
63+
routing {
64+
authenticate("tokenx", "azure") {
65+
arbeidssokerRoutes(startStoppRequestHandler, mockk())
66+
arbeidssokerRoutesV2(startStoppRequestHandler)
67+
}
68+
}
69+
val client = createClient { defaultConfig() }
70+
val id = testCase.id
71+
val person = testCase.person
72+
logger.info("Running test for $id")
73+
personInfoService.setPersonInfo(id, person)
74+
val testConfiguration = TestCaseBuilder(mockOAuthServer, autorisasjonService)
75+
.also { testCase.configure(it) }
76+
val statusV2 =
77+
client.startPeriodeV2(
78+
id,
79+
testConfiguration.authToken,
80+
testCase.forhaandsGodkjent
81+
)
82+
statusV2.status shouldBe testCase.producesHttpResponse
83+
testCase.producesError?.also { expectedErrorResponse ->
84+
val body = statusV2.body<FeilV2>()
85+
body.feilKode.name shouldBe expectedErrorResponse.feilKode.name
86+
val forventetMelding: String =
87+
if (expectedErrorResponse.feilKode == Feil.FeilKode.IKKE_TILGANG) expectedErrorResponse.melding else "Avvist, se 'aarsakTilAvvisning' for detaljer"
88+
body.melding shouldBe forventetMelding
89+
expectedErrorResponse.aarsakTilAvvisning?.regel?.should { aarsak ->
90+
body.aarsakTilAvvisning?.regler?.map { it.id?.name } shouldBe listOf(
91+
aarsak.name
92+
)
93+
}
94+
expectedErrorResponse.aarsakTilAvvisning?.detaljer?.also { expectedDetails ->
95+
body.aarsakTilAvvisning?.detaljer.shouldNotBeNull()
96+
body.aarsakTilAvvisning?.detaljer?.shouldContainExactlyInAnyOrder(
97+
expectedDetails
98+
)
99+
}
100+
}
101+
}
102+
}
103+
"Verifiser Kafka melding" {
104+
val expectedRecord = testCase.producesRecord(kafkaKeys)
105+
if (expectedRecord != null) {
106+
verify(
107+
actual = producer.next(),
108+
expected = expectedRecord
109+
)
110+
producer.next().shouldBeNull()
111+
} else {
112+
producer.next().shouldBeNull()
113+
}
114+
}
115+
}
116+
}
117+
}
118+
}
119+
}
120+
})
121+

apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationTestContext.kt

+22-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package no.nav.paw.arbeidssokerregisteret
33
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
44
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
55
import com.nimbusds.jwt.SignedJWT
6+
import io.kotest.assertions.fail
67
import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder
78
import io.kotest.matchers.shouldBe
89
import io.kotest.matchers.types.shouldBeInstanceOf
@@ -52,9 +53,12 @@ fun MockOAuth2Server.ansattToken(navAnsatt: NavAnsatt): SignedJWT = issueToken(
5253

5354

5455
fun verify(
55-
actual: ProducerRecord<Long, Hendelse>,
56+
actual: ProducerRecord<Long, Hendelse>?,
5657
expected: ProducerRecord<Long, out Hendelse>
5758
) {
59+
if (actual == null) {
60+
fail("Forventet at melding skulle bli produsert, men ingen melding ble funnet")
61+
}
5862
actual.key() shouldBe expected.key()
5963
val actualValue = actual.value()
6064
val expectedValue = expected.value()
@@ -164,3 +168,20 @@ suspend fun HttpClient.startPeriode(identitetsnummer: String, token: SignedJWT?,
164168
)
165169
)
166170
}
171+
172+
suspend fun HttpClient.startPeriodeV2(identitetsnummer: String, token: SignedJWT?, godkjent: Boolean = false): HttpResponse =
173+
put("/api/v2/arbeidssoker/periode") {
174+
token?.also {
175+
bearerAuth(token.serialize())
176+
}
177+
headers {
178+
append(HttpHeaders.ContentType, ContentType.Application.Json)
179+
}
180+
setBody(
181+
ApiV1ArbeidssokerPeriodePutRequest(
182+
identitetsnummer = identitetsnummer,
183+
periodeTilstand = ApiV1ArbeidssokerPeriodePutRequest.PeriodeTilstand.STARTET,
184+
registreringForhaandsGodkjentAvAnsatt = godkjent
185+
)
186+
)
187+
}

apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ProducerMock.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package no.nav.paw.arbeidssokerregisteret
22

3-
import no.nav.paw.arbeidssokerregisteret.intern.v1.Hendelse
43
import org.apache.kafka.clients.consumer.ConsumerGroupMetadata
54
import org.apache.kafka.clients.consumer.OffsetAndMetadata
65
import org.apache.kafka.clients.producer.Callback
@@ -13,10 +12,11 @@ import java.time.Instant
1312
import java.util.concurrent.CompletableFuture
1413
import java.util.concurrent.Future
1514
import java.util.concurrent.LinkedBlockingQueue
15+
import java.util.concurrent.TimeUnit
1616

1717
class ProducerMock<K, V> : Producer<K, V> {
1818
private val queue = LinkedBlockingQueue<ProducerRecord<K, V>>(100)
19-
fun next(): ProducerRecord<K, V> = queue.take()
19+
fun next(): ProducerRecord<K, V>? = queue.poll(100, TimeUnit.MILLISECONDS)
2020

2121
override fun close() {}
2222

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package no.nav.paw.arbeidssokerregisteret
2+
3+
import io.mockk.mockk
4+
import no.nav.paw.arbeidssokerregisteret.application.RequestValidator
5+
import no.nav.paw.arbeidssokerregisteret.application.StartStoppRequestHandler
6+
import no.nav.paw.arbeidssokerregisteret.intern.v1.Hendelse
7+
import no.nav.paw.arbeidssokerregisteret.services.AutorisasjonService
8+
import no.nav.paw.arbeidssokerregisteret.services.PersonInfoService
9+
import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient
10+
import no.nav.paw.kafkakeygenerator.client.inMemoryKafkaKeysMock
11+
12+
fun String.readable(): String =
13+
map { letter -> if (letter.isUpperCase()) " ${letter.lowercase()}" else "$letter" }
14+
.joinToString("")
15+
.replace("oe", "ø")
16+
.replace("aa", "å")
17+
18+
data class TestCaseContext(
19+
val autorisasjonService: AutorisasjonService,
20+
val personInfoService: PersonInfoService,
21+
val producer: ProducerMock<Long, Hendelse>,
22+
val kafkaKeys: KafkaKeysClient,
23+
val startStoppRequestHandler: StartStoppRequestHandler
24+
)
25+
26+
fun initTestCaseContext(): TestCaseContext {
27+
val autorisasjonService = mockk<AutorisasjonService>()
28+
val personInfoService = mockk<PersonInfoService>()
29+
val producer: ProducerMock<Long, Hendelse> = ProducerMock()
30+
val kafkaKeys = inMemoryKafkaKeysMock()
31+
val startStoppRequestHandler = StartStoppRequestHandler(
32+
hendelseTopic = "any",
33+
requestValidator = RequestValidator(
34+
autorisasjonService = autorisasjonService,
35+
personInfoService = personInfoService
36+
),
37+
producer = producer,
38+
kafkaKeysClient = kafkaKeys
39+
)
40+
return TestCaseContext(
41+
autorisasjonService = autorisasjonService,
42+
personInfoService = personInfoService,
43+
producer = producer,
44+
kafkaKeys = kafkaKeys,
45+
startStoppRequestHandler = startStoppRequestHandler
46+
)
47+
}

0 commit comments

Comments
 (0)