SagaSpec

abstract class SagaSpec<T : Any>(block: StatelessSagaDsl<T>.() -> Unit) : AbstractDynamicTestBuilder

Abstract base class for writing stateless saga specification tests using JUnit 5.

This class provides a DSL-based framework for testing stateless sagas by defining scenarios with events and expected command outcomes. It uses JUnit 5's @TestFactory to generate dynamic tests from the specification.

The primary purpose is to facilitate behavior-driven testing of sagas, allowing developers to specify expected command emissions in response to domain events. It enables testing saga logic in isolation without requiring full infrastructure setup.

Example usage:

class CartSagaSpec : SagaSpec<CartSaga>({
on {
val ownerId = generateGlobalId()
val orderItem = OrderItem(
id = generateGlobalId(),
productId = generateGlobalId(),
price = BigDecimal.valueOf(10),
quantity = 10,
)
whenEvent(
event = mockk<OrderCreated> {
every { items } returns listOf(orderItem)
every { fromCart } returns true
},
ownerId = ownerId
) {
expectCommandType(RemoveCartItem::class)
expectCommand<RemoveCartItem> {
aggregateId.id.assert().isEqualTo(ownerId)
body.productIds.assert().hasSize(1)
body.productIds.assert().first().isEqualTo(orderItem.productId)
}
}
}
})

Parameters

block

The test specification block that defines the saga test scenarios. This is a lambda with receiver of type StatelessSagaDsl, where T is the saga type. It contains the test definitions using the DSL methods.

Type Parameters

T

The type of the saga being tested, must be a class that implements the saga logic.

Constructors

Link copied to clipboard
constructor(block: StatelessSagaDsl<T>.() -> Unit)

Properties

Link copied to clipboard

The processor type of the saga being tested, extracted from the generic type parameter.

Functions

Link copied to clipboard
@TestFactory
fun execute(): Stream<DynamicNode>

Executes the saga test specification and returns a stream of dynamic test nodes.