Ejemplo n.º 1
0
        public void SetAsProcessed_should_throw_ArgumentException_if_message_correlation_id_invalid()
        {
            var sut     = new DummySagaState(Guid.NewGuid());
            var message = StartDummySaga.New();

            Assert.Throws <ArgumentException>(() => sut.SetAsProcessed(message));
        }
Ejemplo n.º 2
0
        public async Task RunAsync_should_throw_if_saga_cannot_handle_message()
        {
            var message = UnhandledMessage.New();

            var messageContext = NSubstitute.Substitute.For <IMessageContext <UnhandledMessage> >();

            messageContext.Message.Returns(message);

            var sagaStateService = NSubstitute.Substitute.For <ISagaStateService <DummySaga, DummySagaState> >();

            var state = new DummySagaState(message.CorrelationId);

            sagaStateService.GetAsync(messageContext, Arg.Any <CancellationToken>())
            .Returns((state, Guid.NewGuid()));

            var saga = NSubstitute.Substitute.ForPartsOf <DummySaga>(state);

            var sagaFactory = NSubstitute.Substitute.For <ISagaFactory <DummySaga, DummySagaState> >();

            sagaFactory.Create(state)
            .Returns(saga);

            var logger = NSubstitute.Substitute.For <ILogger <SagaRunner <DummySaga, DummySagaState> > >();

            var transactionManager = NSubstitute.Substitute.For <ITransactionManager>();
            var policyFactory      = NSubstitute.Substitute.For <ISagaPolicyFactory <DummySaga> >();

            var sut = new SagaRunner <DummySaga, DummySagaState>(sagaFactory, sagaStateService, transactionManager, policyFactory, logger);

            await Assert.ThrowsAsync <ConsumerNotFoundException>(() => sut.RunAsync(messageContext, CancellationToken.None));
        }
Ejemplo n.º 3
0
        public void IsCompleted_should_return_true_after_state_is_marked_as_completed()
        {
            var state = new DummySagaState(Guid.NewGuid());

            state.MarkAsCompleted();
            state.IsCompleted().Should().BeTrue();
        }
Ejemplo n.º 4
0
        public async Task GetAsync_should_return_state_from_factory_if_message_can_start_saga()
        {
            var expectedState = new DummySagaState(Guid.NewGuid());

            var message        = StartDummySaga.New();
            var messageContext = NSubstitute.Substitute.For <IMessageContext <StartDummySaga> >();

            messageContext.Message.Returns(message);

            var sagaStateFactory = NSubstitute.Substitute.For <ISagaStateFactory <DummySagaState> >();

            sagaStateFactory.Create(message)
            .Returns(expectedState);

            var sagaStateRepo = NSubstitute.Substitute.For <ISagaStateRepository>();

            sagaStateRepo.LockAsync(message.CorrelationId, expectedState, Arg.Any <CancellationToken>())
            .Returns(Task.FromResult((expectedState, Guid.NewGuid())));

            var sut = new SagaStateService <DummySaga, DummySagaState>(sagaStateFactory, sagaStateRepo);

            var result = await sut.GetAsync(messageContext, CancellationToken.None);

            result.state.Should().Be(expectedState);
        }
Ejemplo n.º 5
0
        public async Task RunAsync_should_use_transaction()
        {
            var message = new StartDummySaga(Guid.NewGuid(), Guid.NewGuid());

            var messageContext = NSubstitute.Substitute.For <IMessageContext <StartDummySaga> >();

            messageContext.Message.Returns(message);

            var sagaStateService = NSubstitute.Substitute.For <ISagaStateService <DummySaga, DummySagaState> >();

            var state = new DummySagaState(message.CorrelationId);

            sagaStateService.GetAsync(messageContext, Arg.Any <CancellationToken>())
            .Returns((state, Guid.NewGuid()));

            var saga = NSubstitute.Substitute.ForPartsOf <DummySaga>(state);

            saga.When(s => s.HandleAsync(Arg.Any <IMessageContext <StartDummySaga> >(), Arg.Any <CancellationToken>()))
            .DoNotCallBase();

            var sagaFactory = NSubstitute.Substitute.For <ISagaFactory <DummySaga, DummySagaState> >();

            sagaFactory.Create(state)
            .Returns(saga);

            var logger = NSubstitute.Substitute.For <ILogger <SagaRunner <DummySaga, DummySagaState> > >();

            var transaction        = NSubstitute.Substitute.For <ITransaction>();
            var transactionManager = NSubstitute.Substitute.For <ITransactionManager>();

            transactionManager.StartTransactionAsync(default)
Ejemplo n.º 6
0
        public void SetState_should_set_state()
        {
            var state = new DummySagaState(Guid.NewGuid());
            var sut   = new DummySaga(state);

            sut.State.Should().Be(state);
        }
Ejemplo n.º 7
0
        public void Create_should_create_valid_instance()
        {
            var state        = new DummySagaState(Guid.NewGuid());
            var expectedSaga = new DummySaga();

            var sp = NSubstitute.Substitute.For <IServiceProvider>();

            sp.GetService(typeof(DummySaga))
            .Returns(expectedSaga);

            var bus = NSubstitute.Substitute.For <IMessageBus>();

            sp.GetService(typeof(IMessageBus))
            .Returns(bus);

            var scope = NSubstitute.Substitute.For <IServiceScope>();

            scope.ServiceProvider.Returns(sp);

            var factory = NSubstitute.Substitute.For <IServiceScopeFactory>();

            factory.CreateScope().Returns(scope);

            sp.GetService(typeof(IServiceScopeFactory))
            .Returns(factory);

            var sut  = new DefaultSagaFactory <DummySaga, DummySagaState>(sp);
            var saga = sut.Create(state);

            saga.Should().NotBeNull();
            saga.State.Should().Be(state);
        }
Ejemplo n.º 8
0
        public void CheckWasProcessed_should_return_true_if_message_processed()
        {
            var sut     = new DummySagaState(Guid.NewGuid());
            var message = new StartDummySaga(Guid.NewGuid(), sut.Id);

            sut.SetAsProcessed(message);
            sut.CheckWasProcessed(message).Should().BeTrue();
        }
Ejemplo n.º 9
0
        public async Task RunAsync_should_retry_if_saga_state_locked()
        {
            var message        = StartDummySaga.New();
            var messageContext = NSubstitute.Substitute.For <IMessageContext <StartDummySaga> >();

            messageContext.Message.Returns(message);

            var sagaStateService = NSubstitute.Substitute.For <ISagaStateService <DummySaga, DummySagaState> >();

            var state = new DummySagaState(message.CorrelationId);

            var firstCall = true;

            sagaStateService.When(s => s.GetAsync(messageContext, Arg.Any <CancellationToken>()))
            .Do(_ =>
            {
                if (firstCall)
                {
                    firstCall = false;
                    throw new LockException("lorem");
                }
            });
            sagaStateService.GetAsync(messageContext, Arg.Any <CancellationToken>())
            .Returns((state, Guid.NewGuid()));

            var saga = NSubstitute.Substitute.ForPartsOf <DummySaga>();

            saga.SetBus(NSubstitute.Substitute.For <IMessageBus>());
            saga.When(s => s.HandleAsync(Arg.Any <IMessageContext <StartDummySaga> >(), Arg.Any <CancellationToken>()))
            .DoNotCallBase();

            var sagaFactory = NSubstitute.Substitute.For <ISagaFactory <DummySaga, DummySagaState> >();

            sagaFactory.Create(state)
            .Returns(saga);

            var logger = NSubstitute.Substitute.For <ILogger <SagaRunner <DummySaga, DummySagaState> > >();

            var uow = NSubstitute.Substitute.For <IUnitOfWork>();

            var sut = new SagaRunner <DummySaga, DummySagaState>(sagaFactory, sagaStateService, uow, logger);

            await sut.RunAsync(messageContext, CancellationToken.None);

            await saga.Received(1)
            .HandleAsync(messageContext, Arg.Any <CancellationToken>());

            await sagaStateService.Received(2)
            .GetAsync(messageContext, Arg.Any <CancellationToken>());
        }
Ejemplo n.º 10
0
        public async Task SaveAsync_should_unlock_state()
        {
            var sagaStateFactory = NSubstitute.Substitute.For <ISagaStateFactory <DummySagaState> >();

            var sagaStateRepo = NSubstitute.Substitute.For <ISagaStateRepository>();

            var sut = new SagaStateService <DummySaga, DummySagaState>(sagaStateFactory, sagaStateRepo);

            var state  = new DummySagaState(Guid.NewGuid());
            var lockId = Guid.NewGuid();

            await sut.SaveAsync(state, lockId, null, CancellationToken.None);

            await sagaStateRepo.Received(1)
            .ReleaseLockAsync(state, lockId, null, CancellationToken.None);
        }
Ejemplo n.º 11
0
        public async Task RunAsync_should_execute_saga_handler_with_policy_when_available()
        {
            var message = new StartDummySaga(Guid.NewGuid(), Guid.NewGuid());

            var messageContext = NSubstitute.Substitute.For <IMessageContext <StartDummySaga> >();

            messageContext.Message.Returns(message);

            var sagaStateService = NSubstitute.Substitute.For <ISagaStateService <DummySaga, DummySagaState> >();

            var state = new DummySagaState(message.CorrelationId);

            sagaStateService.GetAsync(messageContext, Arg.Any <CancellationToken>())
            .Returns((state, Guid.NewGuid()));

            var saga = NSubstitute.Substitute.ForPartsOf <DummySaga>();

            saga.SetBus(NSubstitute.Substitute.For <IMessageBus>());
            saga.When(s => s.HandleAsync(Arg.Any <IMessageContext <StartDummySaga> >(), Arg.Any <CancellationToken>()))
            .DoNotCallBase();

            var sagaFactory = NSubstitute.Substitute.For <ISagaFactory <DummySaga, DummySagaState> >();

            sagaFactory.Create(state)
            .Returns(saga);

            var logger = NSubstitute.Substitute.For <ILogger <SagaRunner <DummySaga, DummySagaState> > >();

            var transactionManager = NSubstitute.Substitute.For <ITransactionManager>();

            var policyFactory = NSubstitute.Substitute.For <ISagaPolicyFactory <DummySaga> >();
            var policy        = new FakePolicy();

            policyFactory.Create <StartDummySaga>().ReturnsForAnyArgs(policy);

            var sut = new SagaRunner <DummySaga, DummySagaState>(sagaFactory, sagaStateService, transactionManager, policyFactory, logger);

            await sut.RunAsync(messageContext, CancellationToken.None);

            await saga.Received(1)
            .HandleAsync(messageContext, Arg.Any <CancellationToken>());
        }
Ejemplo n.º 12
0
        public async Task RunAsync_should_not_execute_handler_if_saga_is_marked_as_completed()
        {
            var message        = new StartDummySaga(Guid.NewGuid(), Guid.NewGuid());
            var messageContext = NSubstitute.Substitute.For <IMessageContext <StartDummySaga> >();

            messageContext.Message.Returns(message);

            var state = new DummySagaState(message.CorrelationId);

            state.MarkAsCompleted();

            var saga = NSubstitute.Substitute.ForPartsOf <DummySaga>(state);

            saga.When(s => s.HandleAsync(Arg.Any <IMessageContext <StartDummySaga> >(), Arg.Any <CancellationToken>()))
            .DoNotCallBase();

            var sagaFactory = NSubstitute.Substitute.For <ISagaFactory <DummySaga, DummySagaState> >();

            sagaFactory.Create(state)
            .Returns(saga);

            var sagaStateService = NSubstitute.Substitute.For <ISagaStateService <DummySaga, DummySagaState> >();

            sagaStateService.GetAsync(messageContext, Arg.Any <CancellationToken>())
            .Returns((state, Guid.NewGuid()));

            var logger = NSubstitute.Substitute.For <ILogger <SagaRunner <DummySaga, DummySagaState> > >();

            var transactionManager = NSubstitute.Substitute.For <ITransactionManager>();
            var policyFactory      = NSubstitute.Substitute.For <ISagaPolicyFactory <DummySaga> >();

            var sut = new SagaRunner <DummySaga, DummySagaState>(sagaFactory, sagaStateService, transactionManager, policyFactory, logger);

            await sut.RunAsync(messageContext, CancellationToken.None);

            sagaFactory.DidNotReceiveWithAnyArgs().Create(null);

            await saga.DidNotReceiveWithAnyArgs()
            .HandleAsync(messageContext, Arg.Any <CancellationToken>());
        }
Ejemplo n.º 13
0
        public async Task RunAsync_should_not_execute_handler_if_message_already_processed()
        {
            var message        = new StartDummySaga(Guid.NewGuid(), Guid.NewGuid());
            var messageContext = NSubstitute.Substitute.For <IMessageContext <StartDummySaga> >();

            messageContext.Message.Returns(message);

            var saga = NSubstitute.Substitute.ForPartsOf <DummySaga>();

            saga.When(s => s.HandleAsync(Arg.Any <IMessageContext <StartDummySaga> >(), Arg.Any <CancellationToken>()))
            .DoNotCallBase();

            var state = new DummySagaState(message.CorrelationId);

            state.SetAsProcessed(message);

            var sagaFactory = NSubstitute.Substitute.For <ISagaFactory <DummySaga, DummySagaState> >();

            sagaFactory.Create(state)
            .Returns(saga);

            var sagaStateService = NSubstitute.Substitute.For <ISagaStateService <DummySaga, DummySagaState> >();

            sagaStateService.GetAsync(messageContext, Arg.Any <CancellationToken>())
            .Returns((state, Guid.NewGuid()));

            var logger = NSubstitute.Substitute.For <ILogger <SagaRunner <DummySaga, DummySagaState> > >();

            var uow = NSubstitute.Substitute.For <IUnitOfWork>();

            var sut = new SagaRunner <DummySaga, DummySagaState>(sagaFactory, sagaStateService, uow, logger);

            await sut.RunAsync(messageContext, CancellationToken.None);

            sagaFactory.DidNotReceiveWithAnyArgs().Create(null);

            await saga.DidNotReceiveWithAnyArgs()
            .HandleAsync(messageContext, Arg.Any <CancellationToken>());
        }
        public async Task SaveAsync_should_persist_outbox()
        {
            var sagaStateFactory = NSubstitute.Substitute.For <ISagaStateFactory <DummySagaState> >();

            var sagaStateRepo = NSubstitute.Substitute.For <ISagaStateRepository>();

            var outboxRepository = NSubstitute.Substitute.For <IOutboxRepository>();

            var sut = new SagaStateService <DummySaga, DummySagaState>(sagaStateFactory, sagaStateRepo, outboxRepository);

            var state = new DummySagaState(Guid.NewGuid());

            var message = StartDummySaga.New();

            state.AddToOutbox(message);
            var lockId = Guid.NewGuid();

            await sut.SaveAsync(state, lockId, CancellationToken.None);

            await outboxRepository.Received(1)
            .AppendAsync(message, Arg.Any <CancellationToken>());
        }
Ejemplo n.º 15
0
        public async Task RunAsync_should_throw_SagaNotFoundException_if_saga_cannot_be_build()
        {
            var message        = new StartDummySaga(Guid.NewGuid(), Guid.NewGuid());
            var messageContext = NSubstitute.Substitute.For <IMessageContext <StartDummySaga> >();

            messageContext.Message.Returns(message);

            var sagaFactory = NSubstitute.Substitute.For <ISagaFactory <DummySaga, DummySagaState> >();

            var sagaStateService = NSubstitute.Substitute.For <ISagaStateService <DummySaga, DummySagaState> >();

            var state = new DummySagaState(message.CorrelationId);

            sagaStateService.GetAsync(messageContext, Arg.Any <CancellationToken>())
            .Returns((state, Guid.NewGuid()));

            var logger = NSubstitute.Substitute.For <ILogger <SagaRunner <DummySaga, DummySagaState> > >();

            var uow = NSubstitute.Substitute.For <IUnitOfWork>();

            var sut = new SagaRunner <DummySaga, DummySagaState>(sagaFactory, sagaStateService, uow, logger);

            await Assert.ThrowsAsync <SagaNotFoundException>(() => sut.RunAsync(messageContext, CancellationToken.None));
        }
Ejemplo n.º 16
0
        public void IsCompleted_should_return_false_when_state_is_initialized_first_time()
        {
            var state = new DummySagaState(Guid.NewGuid());

            state.IsCompleted().Should().BeFalse();
        }
Ejemplo n.º 17
0
        public void CheckWasProcessed_should_throw_ArgumentNullException_if_message_null()
        {
            var sut = new DummySagaState(Guid.NewGuid());

            Assert.Throws <ArgumentNullException>(() => sut.CheckWasProcessed((IMessage)null));
        }