Correlation Id mapping in Sagas when Unit testing

It seems like ConfigureHowToFindSaga() in Sagas is not called when running from a unit test. Im I missing some setup?

Could you share your unit test?

Sure. Bascally, its the ShippingSaga (/ShippingPolicy) sample, to ensure that ShipOrderCommand is not sent until both OrderPlacedEvent and OrderBilledEvent is received. In my Handle()-method, Data.OrderId is null (and ConfigureToFindSaga() is never called). In this test I call Handle with different orderId, but OrderPlaced is still sent


Unit test code:

Test.Saga<ShippingSaga.ShippingSaga>().ExpectNotSend()
.When((saga, context) =>
{

         saga.Handle(new OrderPlacedEvent(ORDER_ID_1, CARD_NR, AMOUNT), context);
         saga.Handle(new OrderBilledEvent(ORDER_ID_2), context);
         return Task.CompletedTask;
     });

Saga Code:

public partial class ShippingSaga : Saga,
IAmStartedByMessages,
IAmStartedByMessages
{
protected override void ConfigureHowToFindSaga(SagaPropertyMapper mapper)
{
mapper.ConfigureMapping(oP => oP.OrderId).ToSaga(sagaData => sagaData.OrderId);
mapper.ConfigureMapping(oB => oB.OrderId).ToSaga(sagaData => sagaData.OrderId);
}

    public Task Handle(OrderPlacedEvent message, IMessageHandlerContext context)
    { 
        this.Data.IsOrderPlaced = true;
        return ProcessOrder(context);
    }

    public Task Handle(OrderBilledEvent message, IMessageHandlerContext context)
    { 
        this.Data.IsOrderBilled = true;
        return ProcessOrder(context);
    }

    public async Task ProcessOrder(IMessageHandlerContext context)
    {
        if (Data.IsOrderPlaced && Data.IsOrderBilled)
        {
            await context.SendLocal(new ShipOrderCommand(Data.OrderId));
            MarkAsComplete();
        }
    } 
}

And your saying that ConfigureHowToFindSaga isn’t invoked but what are the consequences for your test? Trying to understand the problem.

Hi
Yes, that is correct. Im new to NServiceBus, but as I understand it:
The Saga does map the event´s OrderId to its own orderId. So in the unit test I send OB-event for order with orderId “111” and OP-event with orderId “222”. Since there are no concept of orderId in the Saga in the unit test, at the second Handle()-call I have both IsOrderBilled== true and IsOrderPlaced == true, event though they were called with different OrderId.

When come to think of it, maybe I give the Saga too much cred…

How could I test this scenario, i e make sure that OrderPlacedEvent is send when both incomming events are received?

You are saying that in the unit test the saga tester assumes all messages involved relate to the same saga instance?

It could be that this is by design as for example there could be custom saga finders involved which are dependent on persistence availability. Those would also not be invoked.

Your use case to test with 2 different messages on the same saga instance that use different saga correlation ID’s could never occur at runtime as both message would use their own saga instance.

EDIT: What do you want to test? If both order placed event for 2 different order ID’s are received on the same saga instance? That would not be possible where correlation on order ID.

The Test.Saga unit testing helper is just a simple wrapper to make writing unit tests easier, it doesn’t provide the full functionality of Saga handling and doesn’t really look at the message mapping.

We recommend to write your unit tests, assuming that only messages related to the same saga instance are handled by the saga being tested. Your scenario doesn’t have to be tested by your tests, as NServiceBus guarantees that a saga mapped to a specific id will only be used for messages which map to the same id.