Jorge Bo
10/18/2022, 8:15 PMnull cannot be cast to non-null type au.com.dius.pact.core.model.BasePact
java.lang.NullPointerException: null cannot be cast to non-null type au.com.dius.pact.core.model.BasePact
at au.com.dius.pact.consumer.junit5.PactConsumerTestExt.storePactForWrite(PactConsumerTestExt.kt:478)
at au.com.dius.pact.consumer.junit5.PactConsumerTestExt.afterTestExecution(PactConsumerTestExt.kt:459)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterTestExecutionCallbacks$9(TestMethodTestDescriptor.java:233)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$13(TestMethodTestDescriptor.java:273)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$14(TestMethodTestDescriptor.java:273)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:272)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAfterTestExecutionCallbacks(TestMethodTestDescriptor.java:232)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy5.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
uglyog
Jorge Bo
10/19/2022, 12:29 PMJorge Bo
10/19/2022, 12:29 PM@file:OptIn(ExperimentalCoroutinesApi::class)
package io.travelx.flights.itineraryreservations.cdc
import arrow.core.left
import arrow.core.right
import au.com.dius.pact.consumer.MessagePactBuilder
import au.com.dius.pact.consumer.dsl.LambdaDsl.newJsonBody
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt
import au.com.dius.pact.consumer.junit5.PactTestFor
import au.com.dius.pact.consumer.junit5.ProviderType
import au.com.dius.pact.core.model.PactSpecVersion
import au.com.dius.pact.core.model.annotations.Pact
import au.com.dius.pact.core.model.annotations.PactDirectory
import au.com.dius.pact.core.model.messaging.MessagePact
import io.kotest.assertions.arrow.core.shouldBeRight
import io.ktor.client.engine.okhttp.*
import io.mockk.coEvery
import io.mockk.mockk
import io.travelx.flights.itineraryreservations.TestCalendar
import io.travelx.flights.itineraryreservations.core.domain.UnexpectedError
import io.travelx.flights.itineraryreservations.core.domain.commands.CreateReservationCommand
import io.travelx.flights.itineraryreservations.core.domain.model.CreateReservationData
import io.travelx.flights.itineraryreservations.core.usecases.reservation.cancel.CancelPurchaseUseCase
import io.travelx.flights.itineraryreservations.core.usecases.reservation.confirm.ConfirmReservationUseCase
import io.travelx.flights.itineraryreservations.core.usecases.reservation.create.CreateReservationUseCase
import io.travelx.flights.itineraryreservations.infrastructure.messaging.CheckoutSQSMessageProcessor
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import software.amazon.awssdk.services.sqs.model.Message
import software.amazon.awssdk.services.sqs.model.MessageAttributeValue
@ExtendWith(value = [PactConsumerTestExt::class])
@PactTestFor(providerName = "checkout-service", providerType = ProviderType.ASYNCH, pactVersion = PactSpecVersion.V4)
@PactDirectory("pacts")
class ReservationConsumerContractTest {
private val jsonBody = newJsonBody { o ->
o.stringType("purchaseId", "111")
o.stringType("name", "PURCHASE_STARTED")
o.eachLike("products", 1) { items ->
items.stringType("productID", "1")
items.stringType("productType", "FLIGHT")
items.stringType(
"availabilityId",
"RkxZfEVaRV9JR1IoRk98Rk98NTEwMClZXzIwMjItMDktMTJfMDc6MjBfS19LT1dfMEBhPTF8TkVU"
)
}
}.build()
@Pact(consumer = "reservation-service", provider = "checkout-service")
fun pactForReservationBooking(builder: MessagePactBuilder): MessagePact {
return builder
.hasPactWith("checkout-service")
.expectsToReceive("a purchase started message to book a reservation")
.withContent(jsonBody)
.toPact()
}
@Test
@PactTestFor(pactMethod = "pactForReservationBooking")
fun testPactForReservationBooking() = runTest {
val createReservationUseCaseStub = mockk<CreateReservationUseCase>()
val confirmReservationUseCaseStub = mockk<ConfirmReservationUseCase>()
val cancelPurchaseUseCaseStub = mockk<CancelPurchaseUseCase>()
coEvery {
confirmReservationUseCaseStub.invoke(any())
} returns UnexpectedError(IllegalStateException("Confirm should not be called")).left()
coEvery {
cancelPurchaseUseCaseStub.invoke(any())
} returns UnexpectedError(IllegalStateException("Cancel should not be called")).left()
coEvery {
createReservationUseCaseStub.invoke(
CreateReservationCommand(
CreateReservationData(
"111",
"RkxZfEVaRV9JR1IoRk98Rk98NTEwMClZXzIwMjItMDgtMjlfMDY6MzBfS19LT1dfMEBhPTF8TkVU",
"Bearer token",
),
createdAt = TestCalendar.instant(),
)
)
} returns Unit.right()
val sut = CheckoutSQSMessageProcessor(
createReservationUseCaseStub,
confirmReservationUseCaseStub,
cancelPurchaseUseCaseStub,
TestCalendar,
)
val response = sut.invoke(
Message.builder()
.body(
"""
{"purchaseId": "111",
"name": "PURCHASE_STARTED",
"products" : [
{
"productId": "1",
"availabilityId": "RkxZfEVaRV9JR1IoRk98Rk98NTEwMClZXzIwMjItMDgtMjlfMDY6MzBfS19LT1dfMEBhPTF8TkVU",
"productType": "FLIGHT"
}]}"""
).messageId("1IoRk98Rk98NTEwMClZ")
.messageAttributes(
mapOf(
"Authorization" to MessageAttributeValue.builder().stringValue("Bearer token").build(),
"messageDeduplicationId" to MessageAttributeValue.builder().stringValue("1").build(),
"messageGroupId" to MessageAttributeValue.builder().stringValue("10").build()
)
).build()
)
response shouldBeRight Unit
}
}
Jorge Bo
10/24/2022, 7:48 PMuglyog
Jorge Bo
10/25/2022, 8:24 PM@file:OptIn(ExperimentalCoroutinesApi::class)
package io.travelx.flights.itineraryreservations.cdc
import arrow.core.left
import arrow.core.right
import au.com.dius.pact.consumer.MessagePactBuilder
import au.com.dius.pact.consumer.dsl.LambdaDsl.newJsonBody
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt
import au.com.dius.pact.consumer.junit5.PactTestFor
import au.com.dius.pact.consumer.junit5.ProviderType
import au.com.dius.pact.core.model.PactSpecVersion
import au.com.dius.pact.core.model.annotations.Pact
import au.com.dius.pact.core.model.annotations.PactDirectory
import au.com.dius.pact.core.model.messaging.MessagePact
import io.kotest.assertions.arrow.core.shouldBeRight
import io.ktor.client.engine.okhttp.*
import io.mockk.coEvery
import io.mockk.mockk
import io.travelx.flights.itineraryreservations.TestCalendar
import io.travelx.flights.itineraryreservations.core.domain.UnexpectedError
import io.travelx.flights.itineraryreservations.core.domain.commands.CreateReservationCommand
import io.travelx.flights.itineraryreservations.core.domain.model.CreateReservationData
import io.travelx.flights.itineraryreservations.core.usecases.reservation.cancel.CancelPurchaseUseCase
import io.travelx.flights.itineraryreservations.core.usecases.reservation.confirm.ConfirmReservationUseCase
import io.travelx.flights.itineraryreservations.core.usecases.reservation.create.CreateReservationUseCase
import io.travelx.flights.itineraryreservations.infrastructure.messaging.CheckoutSQSMessageProcessor
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import software.amazon.awssdk.services.sqs.model.Message
import software.amazon.awssdk.services.sqs.model.MessageAttributeValue
@ExtendWith(value = [PactConsumerTestExt::class])
@PactTestFor(providerName = "checkout-service", providerType = ProviderType.ASYNCH, pactVersion = PactSpecVersion.V3)
@PactDirectory("pacts")
class ReservationConsumerContractTest {
private val checkoutCompletedJsonBody = newJsonBody { o ->
o.stringType("purchaseId", "111")
o.stringType("name", "PURCHASE_STARTED")
o.eachLike("products", 1) { items ->
items.stringType(
"productId",
"29e44fee-66e6-48c9-950e-3d84bbc675d7"
)
}
}.build()
private val purchaseStartedJsonBody = newJsonBody { o ->
o.stringType("purchaseId", "111")
o.stringType("name", "PURCHASE_STARTED")
o.eachLike("products", 1) { items ->
items.stringType(
"availabilityId",
"RkxZfEVaRV9JR1IoRk98Rk98NTEwMClZXzIwMjItMDktMTJfMDc6MjBfS19LT1dfMEBhPTF8TkVU"
)
items.stringType(
"productId",
""
)
items.stringType(
"productType",
"FLIGHT"
)
}
}.build()
@Pact(consumer = "reservation-service", provider = "checkout-service")
fun pactForReservationBooking(builder: MessagePactBuilder): MessagePact {
return builder
.hasPactWith("checkout-service")
.expectsToReceive("a purchase started message to book a reservation")
.withContent(purchaseStartedJsonBody)
.toPact()
}
@Test
@PactTestFor(pactMethod = "pactForReservationBooking")
fun testPactForReservationBooking(messages: List<au.com.dius.pact.core.model.messaging.Message>) = runTest {
val createReservationUseCaseStub = mockk<CreateReservationUseCase>()
val confirmReservationUseCaseStub = mockk<ConfirmReservationUseCase>()
val cancelPurchaseUseCaseStub = mockk<CancelPurchaseUseCase>()
coEvery {
confirmReservationUseCaseStub.invoke(any())
} returns UnexpectedError(IllegalStateException("Confirm should not be called")).left()
coEvery {
cancelPurchaseUseCaseStub.invoke(any())
} returns UnexpectedError(IllegalStateException("Cancel should not be called")).left()
coEvery {
createReservationUseCaseStub.invoke(
CreateReservationCommand(
CreateReservationData(
"111",
"RkxZfEVaRV9JR1IoRk98Rk98NTEwMClZXzIwMjItMDktMTJfMDc6MjBfS19LT1dfMEBhPTF8TkVU",
"Bearer token",
),
createdAt = TestCalendar.instant(),
)
)
} returns Unit.right()
val sut = CheckoutSQSMessageProcessor(
createReservationUseCaseStub,
confirmReservationUseCaseStub,
cancelPurchaseUseCaseStub,
TestCalendar,
)
for (message in messages) {
val response = sut.invoke(
Message.builder()
.body(message.contentsAsString())
.messageId("1IoRk98Rk98NTEwMClZ")
.messageAttributes(
mapOf(
"Authorization" to MessageAttributeValue.builder().stringValue("Bearer token").build(),
"messageDeduplicationId" to MessageAttributeValue.builder().stringValue("1").build(),
"messageGroupId" to MessageAttributeValue.builder().stringValue("10").build()
)
).build()
)
response shouldBeRight Unit
}
}
}
uglyog
@Pact(consumer = "reservation-service", provider = "checkout-service")
fun pactForReservationBooking(builder: MessagePactBuilder): MessagePact
uglyog
Jorge Bo
10/26/2022, 1:04 PMfun testPactForReservationBooking(messages: List<au.com.dius.pact.core.model.messaging.Message>)
is required, i have seen examples written in different ways. Some create the message by itself and other let pact create them. I’m finding a bit difficult to understand the documentation.