public async Task Project_CancelMessageWithCorrectSequenceNumber_ShouldCancelHandlerAndNotThrowSequenceNumberException() { await _sequenceNumberRepository.Store(new Dictionary <string, int> { { "A", 10 } }); var messageEnvelope = new FakeMessageEnvelope(10, new RegisteredMessageA()); var isCancelled = false; _projectionMocks[0].SetupGet(x => x.Key).Returns("A"); _projectionMocks[0] .Setup(x => x.Handle(It.IsAny <Func <object> >(), messageEnvelope, It.IsAny <CancellationToken>())) .Returns <object, FakeMessageEnvelope, CancellationToken>(async(_, __, token) => { await Task.Delay(20).ConfigureAwait(false); isCancelled = token.IsCancellationRequested; return(false); }); var projections = new HashSet <IProjection <string, FakeMessageEnvelope> >(_projectionMocks.Take(1).Select(x => x.Object)); var projector = new Projector <string, FakeMessageEnvelope, TestNextSequenceNumberRepository>(projections, _factoryMock.Object); var cancellationTokenSource = new CancellationTokenSource(5); await projector.Project(messageEnvelope, cancellationTokenSource.Token).ConfigureAwait(false); Assert.True(isCancelled); }
public async Task Project_WithProjectionThatResolvesConnection_ShouldCreateResolveDisposeLifetimeScopeInCorrectOrder() { await _sequenceNumberRepository.Store(new Dictionary <string, int> { { "A", 5 } }); var messageEnvelope = new FakeMessageEnvelope(5, new RegisteredMessageA()); var connectionType = typeof(ConnectionA); _projectionMocks[0].SetupGet(x => x.Key).Returns("A"); _projectionMocks[0].SetupGet(x => x.ConnectionType).Returns(connectionType); _projectionMocks[0] .Setup(x => x.Handle(It.IsAny <Func <object> >(), messageEnvelope, CancellationToken.None)) .Callback <Func <object>, FakeMessageEnvelope, CancellationToken>((connectionResolver, _, __) => { Assert.That(connectionResolver(), Is.Not.Null); }) .Returns(() => Task.FromResult(true)); var projections = new HashSet <IProjection <string, FakeMessageEnvelope> >(_projectionMocks.Take(1).Select(x => x.Object)); var projector = new Projector <string, FakeMessageEnvelope, TestNextSequenceNumberRepository>(projections, _factoryMock.Object); // Get the sequence number first so this scope creation/disposal does not influence our test await projector.GetNextSequenceNumber(); var executionOrder = 0; _factoryMock.Reset(); _factoryMock .Setup(x => x.BeginLifetimeScope()) .Callback(() => Assert.That(executionOrder++, Is.EqualTo(0))) .Returns(() => { var scopeMock = new Mock <IDependencyLifetimeScope>(); scopeMock .Setup(x => x.Resolve(typeof(TestNextSequenceNumberRepository))) .Returns(_sequenceNumberRepository); scopeMock .Setup(x => x.Resolve(connectionType)) .Callback(() => Assert.That(executionOrder++, Is.EqualTo(1))) .Returns(() => new FakeConnection()); scopeMock .Setup(x => x.Dispose()) .Callback(() => Assert.That(executionOrder++, Is.EqualTo(2))); return(scopeMock.Object); }); // ReSharper disable once MethodSupportsCancellation await projector.Project(messageEnvelope); Assert.That(executionOrder, Is.EqualTo(3)); }
public async Task Handle_MessageWithoutRegisteredHandler_ShouldReturnFalse() { var projectionMock = new Mock <TestProjection>(null) { CallBase = true }; var unregisteredMessageEnvelope = new FakeMessageEnvelope(1, new UnregisteredMessage()); IProjection <string, FakeMessageEnvelope> projection = projectionMock.Object; Assert.That(await projection.Handle(_connectionFactory, unregisteredMessageEnvelope, CancellationToken.None), Is.False); }
public async Task Project_MessageWithWrongSequenceNumber_ShouldThrowException() { await _sequenceNumberRepository.Store(new Dictionary <string, int> { { "A", 5 }, { "B", 6 }, { "C", 3 } }); _projectionMocks[0].SetupGet(x => x.Key).Returns("A"); _projectionMocks[1].SetupGet(x => x.Key).Returns("B"); _projectionMocks[2].SetupGet(x => x.Key).Returns("C"); var messageEnvelope = new FakeMessageEnvelope(2, new RegisteredMessageA()); var projections = new HashSet <IProjection <string, FakeMessageEnvelope> >(_projectionMocks.Select(x => x.Object)); var projector = new Projector <string, FakeMessageEnvelope, TestNextSequenceNumberRepository>(projections, _factoryMock.Object); var ex = Assert.ThrowsAsync <ArgumentOutOfRangeException>(() => projector.Project(messageEnvelope)); Assert.That(ex.ParamName, Is.EqualTo("SequenceNumber")); }
public void Handle_TwoDifferentMessages_ShouldCallCorrectHandlerWithCorrectArguments() { var connectionMock = new Mock <FakeConnection>(); Func <object> connectionFactory = () => connectionMock.Object; var token = new CancellationToken(); var messageA = new RegisteredMessageA(); var messageB = new RegisteredMessageB(); var messageEnvelopeA = new FakeMessageEnvelope(1, messageA); var messageEnvelopeB = new FakeMessageEnvelope(2, messageB); IProjection <string, FakeMessageEnvelope> projection = new TestProjection("A"); projection.Handle(connectionFactory, messageEnvelopeA, token); projection.Handle(connectionFactory, messageEnvelopeB, token); connectionMock.Verify(x => x.UpdateA(messageEnvelopeA, messageA), Times.Once); connectionMock.Verify(x => x.UpdateB(messageEnvelopeB, messageB, token), Times.Once); }
public async Task UseAutofac_ProjectMessage_ShouldResolveConnection() { var sequence = 1; var messageEnvelope = new FakeMessageEnvelope(sequence, new FakeMessage()); var projectionMock = new Mock <IProjection <string, FakeMessageEnvelope> >(); projectionMock.SetupGet(x => x.Key).Returns("SomeKey"); projectionMock.SetupGet(x => x.ConnectionType).Returns(typeof(FakeConnection)); projectionMock .Setup(x => x.Handle(It.IsAny <Func <object> >(), messageEnvelope, It.IsAny <CancellationToken>())) .Callback <Func <object>, FakeMessageEnvelope, CancellationToken>( (resolver, _, __) => { var connection = resolver(); Assert.That(connection, Is.Not.Null); Assert.That(connection.GetType(), Is.EqualTo(typeof(FakeConnection))); }) .Returns(() => Task.FromResult(true)); var services = new ContainerBuilder(); services.RegisterType <FakeConnection>().AsSelf().InstancePerLifetimeScope(); services.RegisterType <FakeNextSequenceNumberRepository>().AsSelf().InstancePerLifetimeScope(); services.RegisterInstance(projectionMock.Object).AsImplementedInterfaces().SingleInstance(); services.Register(ctx => new ProjectorBuilder <string, FakeMessageEnvelope>() .RegisterProjectionsFromAutofac(ctx) .UseAutofacDependencyLifetimeScopeFactory(ctx) .Build <FakeNextSequenceNumberRepository>()) .AsSelf() .SingleInstance(); var container = services.Build(); var projector = container.Resolve <Projector <string, FakeMessageEnvelope, FakeNextSequenceNumberRepository> >(); // ReSharper disable once MethodSupportsCancellation await projector.Project(messageEnvelope); projectionMock.Verify(x => x.Handle( It.IsAny <Func <object> >(), It.IsAny <FakeMessageEnvelope>(), It.IsAny <CancellationToken>()), Times.Once); }
public async Task Project_MessageWithCorrectSequenceNumber_ShouldIncrementSequenceNumber() { await _sequenceNumberRepository.Store(new Dictionary <string, int> { { "A", 5 }, { "B", 6 }, { "C", 3 } }); _projectionMocks[0].SetupGet(x => x.Key).Returns("A"); _projectionMocks[1].SetupGet(x => x.Key).Returns("B"); _projectionMocks[2].SetupGet(x => x.Key).Returns("C"); var messageEnvelope = new FakeMessageEnvelope(3, new RegisteredMessageA()); var projections = new HashSet <IProjection <string, FakeMessageEnvelope> >(_projectionMocks.Select(x => x.Object)); var projector = new Projector <string, FakeMessageEnvelope, TestNextSequenceNumberRepository>(projections, _factoryMock.Object); Assert.That(await projector.GetNextSequenceNumber(), Is.EqualTo(3)); await projector.Project(messageEnvelope); Assert.That(await projector.GetNextSequenceNumber(), Is.EqualTo(4)); }
public async Task Project_SecondProjectionThrowsException_ProjectShouldThrowExceptionAfterStoringCorrectSequenceNumbers() { await _sequenceNumberRepository.Store(new Dictionary <string, int> { { "A", 50 }, { "B", 50 }, { "C", 50 } }); _projectionMocks[0].SetupGet(x => x.Key).Returns("A"); _projectionMocks[1].SetupGet(x => x.Key).Returns("B"); _projectionMocks[2].SetupGet(x => x.Key).Returns("C"); var messageEnvelope = new FakeMessageEnvelope(50, new RegisteredMessageA()); _projectionMocks[1].Setup(x => x.Handle(It.IsAny <Func <object> >(), messageEnvelope, CancellationToken.None)) .Callback(() => { throw new DivideByZeroException(); }); var projections = new HashSet <IProjection <string, FakeMessageEnvelope> >(_projectionMocks.Select(x => x.Object)); var projector = new Projector <string, FakeMessageEnvelope, TestNextSequenceNumberRepository>(projections, _factoryMock.Object); Assert.ThrowsAsync <DivideByZeroException>(() => projector.Project(messageEnvelope)); Assert.That(_sequenceNumberRepository["A"], Is.EqualTo(51)); Assert.That(_sequenceNumberRepository["B"], Is.EqualTo(50)); Assert.That(_sequenceNumberRepository["C"], Is.EqualTo(50)); }