Class SagaTestFixture<T>

java.lang.Object
org.axonframework.test.saga.SagaTestFixture<T>
Type Parameters:
T - the type of Saga under test
All Implemented Interfaces:
AutoCloseable, ContinuedGivenState, FixtureConfiguration, WhenState

public class SagaTestFixture<T> extends Object implements FixtureConfiguration, ContinuedGivenState, AutoCloseable
Fixture for testing Sagas in a given-when-then style, carrying the Axon Framework 4 API so a migrating test suite keeps its shape.

A layer over AxonTestFixture: the Saga is registered on a subscribing event processor, which handles on the publishing thread, so a "when" call has already completed by the time the assertions run and no waiting is needed. The Sagas are kept in an InMemorySagaStore, which the store assertions read.

The fixture's DeadlineManager is a StubDeadlineManager, so a Saga handler taking a DeadlineManager parameter schedules on it. Nothing fires on its own: moving the fixture's time, through whenTimeElapses(Duration) and its siblings, fires every deadline due by then in the Saga that scheduled it.

When given an event payload, the fixture resolves its Axon Framework 5 message type from that payload. When given an EventMessage, it preserves the message's declared type. Axon Framework 5 routes by that type, so it must match the type supported by the intended Saga handler even when the message payload has the handler's Java type.

Example:


 SagaTestFixture<OrderSaga> fixture = new SagaTestFixture<>(OrderSaga.class);
 fixture.givenAPublished(new OrderPlaced("order-1"))
        .whenPublishingA(new OrderShipped("shipment-of-order-1"))
        .expectActiveSagas(1)
        .expectAssociationWith("orderId", "order-1");
 
A test that does not need the Axon Framework 4 API can drive the same Saga through AxonTestFixture directly and use SagaAssertions for the store assertions.
Since:
5.4.0
Author:
Allard Buijze, Mateusz Nowak
  • Constructor Details

    • SagaTestFixture

      public SagaTestFixture(Class<T> sagaType)
      Creates an instance for testing Sagas of the given sagaType.
      Parameters:
      sagaType - the type of Saga under test
  • Method Details

    • withTransienceCheckDisabled

      @Deprecated(forRemoval=true) public FixtureConfiguration withTransienceCheckDisabled()
      Deprecated, for removal: This API element is subject to removal in a future version.
      Description copied from interface: FixtureConfiguration
      Does nothing, and is kept only so an Axon Framework 4 test suite still compiles.

      Axon Framework 4 refused a Saga holding an injected resource in a field that was not transient, because the Saga is serialized into the SagaStore and the resource would go with it. This method turned that check off.

      Axon Framework 5 has no such check, and rebuilding it would not help. It worked by comparing each field against the resource injector's list, and there is no injector; and its advice no longer applies, since transient is a Java serialization marker while a Saga is now serialized through a Converter. A Saga can still hold infrastructure in a field, but nothing puts it there on the Saga's behalf, and serializing it fails loudly.

      Specified by:
      withTransienceCheckDisabled in interface FixtureConfiguration
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • customize

      public FixtureConfiguration customize(UnaryOperator<MessagingConfigurer> customization)
      Description copied from interface: FixtureConfiguration
      Customizes the MessagingConfigurer the fixture builds the Saga on, for anything this interface does not expose.

      The Saga, its store and its event processor are registered before the given customization is applied, so it can add to them or replace what they registered.

      Specified by:
      customize in interface FixtureConfiguration
      Parameters:
      customization - the customization to apply to the configurer
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • registerResource

      public void registerResource(Object resource)
      Description copied from interface: FixtureConfiguration
      Registers the given resource, making it available to Saga handler methods declaring a parameter of an assignable type.

      Registering two resources of the same type makes the last one win, as it did in Axon Framework 4. Unlike Axon Framework 4, the resource is not injected into the Saga's fields.

      Specified by:
      registerResource in interface FixtureConfiguration
      Parameters:
      resource - the resource to make available to the Saga's handler methods
    • registerParameterResolverFactory

      public FixtureConfiguration registerParameterResolverFactory(ParameterResolverFactory parameterResolverFactory)
      Description copied from interface: FixtureConfiguration
      Registers the given parameterResolverFactory, used to resolve the parameters of the Saga's handler methods.
      Specified by:
      registerParameterResolverFactory in interface FixtureConfiguration
      Parameters:
      parameterResolverFactory - the factory resolving handler method parameters
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • registerHandlerDefinition

      public FixtureConfiguration registerHandlerDefinition(HandlerDefinition handlerDefinition)
      Description copied from interface: FixtureConfiguration
      Registers the given handlerDefinition, used to create the Saga's handlers.
      Specified by:
      registerHandlerDefinition in interface FixtureConfiguration
      Parameters:
      handlerDefinition - the definition creating the Saga's handlers
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • registerHandlerEnhancerDefinition

      public FixtureConfiguration registerHandlerEnhancerDefinition(HandlerEnhancerDefinition definition)
      Description copied from interface: FixtureConfiguration
      Registers the given handlerEnhancerDefinition, used to enhance the Saga's handlers.
      Specified by:
      registerHandlerEnhancerDefinition in interface FixtureConfiguration
      Parameters:
      definition - the definition enhancing the Saga's handlers
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • registerDeadlineDispatchInterceptor

      public FixtureConfiguration registerDeadlineDispatchInterceptor(MessageDispatchInterceptor<? super DeadlineMessage> deadlineDispatchInterceptor)
      Description copied from interface: FixtureConfiguration
      Registers a deadline dispatch interceptor which will always be invoked before a deadline is dispatched (scheduled) on the DeadlineManager to perform a task specified in the interceptor.
      Specified by:
      registerDeadlineDispatchInterceptor in interface FixtureConfiguration
      Parameters:
      deadlineDispatchInterceptor - the interceptor for dispatching (scheduling) deadlines
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • registerDeadlineHandlerInterceptor

      public FixtureConfiguration registerDeadlineHandlerInterceptor(MessageHandlerInterceptor<? super DeadlineMessage> deadlineHandlerInterceptor)
      Description copied from interface: FixtureConfiguration
      Registers a deadline handler interceptor which will always be invoked before a deadline is handled to perform a task specified in the interceptor.
      Specified by:
      registerDeadlineHandlerInterceptor in interface FixtureConfiguration
      Parameters:
      deadlineHandlerInterceptor - the interceptor for handling deadlines
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • registerEventHandlerInterceptor

      public FixtureConfiguration registerEventHandlerInterceptor(MessageHandlerInterceptor<? super EventMessage> interceptor)
      Description copied from interface: FixtureConfiguration
      Registers the given interceptor, invoked around the Saga's event handling.

      Interceptors are invoked in registration order, as they were in Axon Framework 4.

      Specified by:
      registerEventHandlerInterceptor in interface FixtureConfiguration
      Parameters:
      interceptor - the interceptor to invoke around the Saga's event handling
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • registerFieldFilter

      public FixtureConfiguration registerFieldFilter(FieldFilter fieldFilter)
      Description copied from interface: FixtureConfiguration
      Registers the given fieldFilter, defining which fields are compared when matching messages.
      Specified by:
      registerFieldFilter in interface FixtureConfiguration
      Parameters:
      fieldFilter - the filter defining which fields to compare
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • registerIgnoredField

      public FixtureConfiguration registerIgnoredField(Class<?> declaringClass, String fieldName)
      Description copied from interface: FixtureConfiguration
      Indicates that a field with the given fieldName, declared in the given declaringClass, is ignored when comparing messages.
      Specified by:
      registerIgnoredField in interface FixtureConfiguration
      Parameters:
      declaringClass - the class declaring the field
      fieldName - the name of the field to ignore
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • registerStartRecordingCallback

      public FixtureConfiguration registerStartRecordingCallback(Runnable callback)
      Description copied from interface: FixtureConfiguration
      Registers the given callback, invoked when the fixture starts recording what the Saga does, which is when the "when" phase begins.
      Specified by:
      registerStartRecordingCallback in interface FixtureConfiguration
      Parameters:
      callback - the callback to invoke when recording starts
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • setCallbackBehavior

      public void setCallbackBehavior(CallbackBehavior callbackBehavior)
      Description copied from interface: FixtureConfiguration
      Sets the behaviour answering commands that no subscribed handler takes.

      Defaults to a DefaultCallbackBehavior, which answers null, as Axon Framework 4 did. A command that does reach a handler subscribed through FixtureConfiguration.customize(UnaryOperator) is answered by that handler instead.

      Specified by:
      setCallbackBehavior in interface FixtureConfiguration
      Parameters:
      callbackBehavior - the behaviour deciding what such a command returns
    • suppressExceptionInGivenPhase

      public FixtureConfiguration suppressExceptionInGivenPhase(boolean suppress)
      Description copied from interface: FixtureConfiguration
      Sets whether a failure of a Saga handler during the "given" phase is suppressed rather than thrown.

      Defaults to false, meaning a failure during the "given" phase surfaces. Axon Framework 4's FixtureConfiguration documented the opposite default while its implementation did the same as this; the implementation is what is kept.

      Specified by:
      suppressExceptionInGivenPhase in interface FixtureConfiguration
      Parameters:
      suppress - whether to suppress a failure during the "given" phase
      Returns:
      the current FixtureConfiguration, for fluent interfacing
    • getEventBus

      public EventBus getEventBus()
      Description copied from interface: FixtureConfiguration
      The EventBus the fixture publishes on.

      Axon Framework 5 splits an EventBus into a EventSink for publishing and a SubscribableEventSource for subscribing. A test only needs the publishing half, but the whole bus is returned so that fixture.getEventBus().subscribe(..) keeps working, as it did in Axon Framework 4.

      Axon Framework 5 obtains the bus from the application configuration. Calling this method therefore builds and starts the fixture; make all fixture registrations before requesting the bus.

      Specified by:
      getEventBus in interface FixtureConfiguration
      Returns:
      the event bus the fixture publishes on
    • getCommandBus

      public CommandBus getCommandBus()
      Description copied from interface: FixtureConfiguration
      The CommandBus the Saga dispatches on.

      Axon Framework 5 obtains the bus from the application configuration. Calling this method therefore builds and starts the fixture; make all fixture registrations before requesting the bus.

      Specified by:
      getCommandBus in interface FixtureConfiguration
      Returns:
      the command bus the Saga dispatches on
    • givenAggregate

      public GivenAggregateEventPublisher givenAggregate(String aggregateIdentifier)
      Description copied from interface: FixtureConfiguration
      Use this method to indicate that an aggregate with given identifier published certain events.

      Can be chained to build natural sentences: givenAggregate(someIdentifier).published(someEvents)

      Specified by:
      givenAggregate in interface FixtureConfiguration
      Parameters:
      aggregateIdentifier - The identifier of the aggregate the events should appear to come from
      Returns:
      an object that allows registration of the actual events to send
    • givenAPublished

      public ContinuedGivenState givenAPublished(Object event)
      Description copied from interface: FixtureConfiguration
      Indicates that the given event has been published in the past. This event is sent to the associated Sagas.
      Specified by:
      givenAPublished in interface FixtureConfiguration
      Parameters:
      event - The event to publish
      Returns:
      an object that allows chaining of more given state
    • givenAPublished

      public ContinuedGivenState givenAPublished(Object event, Map<String,String> metadata)
      Description copied from interface: FixtureConfiguration
      Indicates that the given event with given metadata has been published in the past. This event is sent to the associated Sagas.
      Specified by:
      givenAPublished in interface FixtureConfiguration
      Parameters:
      event - The event to publish
      metadata - The metadata to attach to the event
      Returns:
      an object that allows chaining of more given state
    • givenNoPriorActivity

      public WhenState givenNoPriorActivity()
      Description copied from interface: FixtureConfiguration
      Indicates that no relevant activity has occurred in the past.
      Specified by:
      givenNoPriorActivity in interface FixtureConfiguration
      Returns:
      an object that allows the definition of the activity to measure Saga behavior
    • andThenAggregate

      public GivenAggregateEventPublisher andThenAggregate(String aggregateIdentifier)
      Description copied from interface: ContinuedGivenState
      Use this method to indicate that an aggregate with given identifier published certain events.

      Can be chained to build natural sentences: andThenAggregate(someIdentifier).published(someEvents)

      Specified by:
      andThenAggregate in interface ContinuedGivenState
      Parameters:
      aggregateIdentifier - The identifier of the aggregate the events should appear to come from
      Returns:
      an object that allows registration of the actual events to send
    • andThenAPublished

      public ContinuedGivenState andThenAPublished(Object event)
      Description copied from interface: ContinuedGivenState
      Indicates that the given event has been published in the past. This event is sent to the associated sagas.
      Specified by:
      andThenAPublished in interface ContinuedGivenState
      Parameters:
      event - The event to publish
      Returns:
      an object that allows chaining of more given state
    • andThenAPublished

      public ContinuedGivenState andThenAPublished(Object event, Map<String,String> metadata)
      Description copied from interface: ContinuedGivenState
      Indicates that the given event with given metadata has been published in the past. This event is sent to the associated sagas.
      Specified by:
      andThenAPublished in interface ContinuedGivenState
      Parameters:
      event - The event to publish
      metadata - The metadata to attach to the event
      Returns:
      an object that allows chaining of more given state
    • whenAggregate

      public WhenAggregateEventPublisher whenAggregate(String aggregateIdentifier)
      Description copied from interface: WhenState
      Use this method to indicate that an aggregate with given identifier should publish certain events, while recording the outcome. In contrast to the given and andThen methods, this method starts recording activity on the event sink and command bus.

      Can be chained to build natural sentences: whenAggregate(someIdentifier).publishes(anEvent)

      Note that if you inject resources using FixtureConfiguration.registerResource(Object), you may need to reset them yourself if they are manipulated by the Saga in the "given" stage of the test.

      Specified by:
      whenAggregate in interface WhenState
      Parameters:
      aggregateIdentifier - The identifier of the aggregate the events should appear to come from
      Returns:
      an object that allows registration of the actual events to send
    • whenPublishingA

      public FixtureExecutionResult whenPublishingA(Object event)
      Description copied from interface: WhenState
      Use this method to indicate an event is published, while recording the outcome.

      Note that if you inject resources using FixtureConfiguration.registerResource(Object), you may need to reset them yourself if they are manipulated by the Saga in the "given" stage of the test.

      Specified by:
      whenPublishingA in interface WhenState
      Parameters:
      event - the event to publish
      Returns:
      an object allowing you to verify the test results
    • whenPublishingA

      public FixtureExecutionResult whenPublishingA(Object event, Map<String,String> metadata)
      Description copied from interface: WhenState
      Use this method to indicate an event is published with given additional metadata, while recording the outcome.

      Note that if you inject resources using FixtureConfiguration.registerResource(Object), you may need to reset them yourself if they are manipulated by the Saga in the "given" stage of the test.

      Specified by:
      whenPublishingA in interface WhenState
      Parameters:
      event - the event to publish
      metadata - The metadata to attach to the event
      Returns:
      an object allowing you to verify the test results
    • givenCurrentTime

      public ContinuedGivenState givenCurrentTime(Instant currentTime)
      Description copied from interface: FixtureConfiguration
      Sets the time the fixture starts from.
      Specified by:
      givenCurrentTime in interface FixtureConfiguration
      Parameters:
      currentTime - The time to start the fixture at
      Returns:
      an object that allows chaining of more given state
    • andThenTimeElapses

      public ContinuedGivenState andThenTimeElapses(Duration elapsedTime)
      Description copied from interface: ContinuedGivenState
      Simulate time shifts in the current given state. This can be useful when the time between given events is of importance.
      Specified by:
      andThenTimeElapses in interface ContinuedGivenState
      Parameters:
      elapsedTime - The amount of time that will elapse
      Returns:
      an object that allows registration of the actual events to send
    • andThenTimeAdvancesTo

      public ContinuedGivenState andThenTimeAdvancesTo(Instant newDateTime)
      Description copied from interface: ContinuedGivenState
      Simulate time shifts in the current given state. This can be useful when the time between given events is of importance.
      Specified by:
      andThenTimeAdvancesTo in interface ContinuedGivenState
      Parameters:
      newDateTime - The time to advance the clock to
      Returns:
      an object that allows registration of the actual events to send
    • whenTimeElapses

      public FixtureExecutionResult whenTimeElapses(Duration elapsedTime)
      Description copied from interface: WhenState
      Mimic an elapsed time with no relevant activity for the Saga. If any Events are scheduled to be published within this time frame, they are published. All activity by the Saga on the command bus and event sink (meaning that scheduled events are excluded) is recorded.

      Note that if you inject resources using FixtureConfiguration.registerResource(Object), you may need to reset them yourself if they are manipulated by the Saga in the "given" stage of the test.

      Specified by:
      whenTimeElapses in interface WhenState
      Parameters:
      elapsedTime - The amount of time to elapse
      Returns:
      an object allowing you to verify the test results
    • whenTimeAdvancesTo

      public FixtureExecutionResult whenTimeAdvancesTo(Instant newDateTime)
      Description copied from interface: WhenState
      Mimic an elapsed time with no relevant activity for the Saga. If any Events are scheduled to be published within this time frame, they are published. All activity by the Saga on the command bus and event sink (meaning that scheduled events are excluded) is recorded.

      Note that if you inject resources using FixtureConfiguration.registerResource(Object), you may need to reset them yourself if they are manipulated by the Saga in the "given" stage of the test.

      Specified by:
      whenTimeAdvancesTo in interface WhenState
      Parameters:
      newDateTime - The time to advance the clock to
      Returns:
      an object allowing you to verify the test results
    • currentTime

      public Instant currentTime()
      The time as the fixture's scheduler sees it.

      This is the time of the fixture's StubDeadlineManager. Axon Framework 4 reported the time of its event scheduler, which it moved in step with the deadline manager.

      Specified by:
      currentTime in interface FixtureConfiguration
      Returns:
      the current time of the fixture's scheduler
    • stop

      public void stop()
      Shuts the configuration this fixture started down.

      New in Axon Framework 5: the fixture runs a started AxonConfiguration, which holds an event processor that has to be stopped.

    • close

      public void close()
      Shuts down the configuration started by this fixture.

      This alias for stop() allows a fixture to be used in a try-with-resources statement, ensuring that Axon Framework 5 lifecycle handlers run even when a test fails.

      Specified by:
      close in interface AutoCloseable