public void Process_ApplyingEventToAggregateThrowsException_ShouldNotBeginTransaction() { // Arrange var serviceScopeMock = new Mock <IServiceScope>(); var serviceScopeFactoryMock = NewServiceScopeFactoryMock; serviceScopeFactoryMock.Setup(x => x.CreateScope()).Returns(() => serviceScopeMock.Object); var commandHandlingContext = new CommandHandlingContext(); serviceScopeMock .Setup(x => x.GetService(typeof(CommandHandlingContext))) .Returns(commandHandlingContext); serviceScopeMock .Setup(x => x.GetService(typeof(IEnumerable <ICommandHandler <FakeCommand> >))) .Returns(new[] { new FakeCommandHandler(commandHandlingContext, x => x.DoSomethingBad()) }); var transactionMock = new Mock <IEventStoreTransaction <string, object> >(); var eventStoreMock = NewEventStoreMock; eventStoreMock .Setup(x => x.BeginTransaction(It.IsAny <CommandHandlingContext>())) .Returns(transactionMock.Object); var processor = new CommandProcessor(serviceScopeFactoryMock.Object, eventStoreMock.Object, NewEventDispatcherMock.Object); // Act / Assert Func <Task> action = () => processor.Process(new FakeCommand()); action.Should().Throw <KeyNotFoundException>(); eventStoreMock.Verify(x => x.BeginTransaction(It.IsAny <CommandHandlingContext>()), Times.Never); }
public void Get_UnknownAggregateRoot_ShouldThrowException() { // Arrange var commandHandlingContext = new CommandHandlingContext(); commandHandlingContext.CreateUnitOfWork <string, object>(); var unknownIdentifier = Guid.NewGuid().ToString("N"); var eventStoreMock = NewEventStoreMock; eventStoreMock.Setup(x => x.GetEvents(unknownIdentifier, 1)).ReturnsAsync(Array.Empty <object>()); var repository = new Repository <FakeAggregateRoot>(eventStoreMock.Object, commandHandlingContext); // Act / Assert Func <Task> action = () => repository.Get(unknownIdentifier); action.Should().Throw <AggregateRootNotFoundException <string> >() .WithMessage($"Exception for aggregate root with identifier '{unknownIdentifier}': Aggregate root not found") .Which.Identifier.Should().Be(unknownIdentifier); // Arrange eventStoreMock.Setup(x => x.GetEvents(unknownIdentifier, 1)).ReturnsAsync((object[])null); // Act / Assert action.Should().Throw <AggregateRootNotFoundException <string> >() .WithMessage($"Exception for aggregate root with identifier '{unknownIdentifier}': Aggregate root not found") .Which.Identifier.Should().Be(unknownIdentifier); }
public async Task Get_KnownAggregateRoot_ShouldReturnInitializedAggregateRoot() { // Arrange var commandHandlingContext = new CommandHandlingContext(); commandHandlingContext.CreateUnitOfWork <string, object>(); var knownIdentifier = Guid.NewGuid().ToString("N"); var eventStoreMock = NewEventStoreMock; eventStoreMock.Setup(x => x.GetEvents(knownIdentifier, 0)).ReturnsAsync(new object[] { new EventA(), new EventB(), new EventA(), }); var repository = new Repository <FakeAggregateRoot>(eventStoreMock.Object, commandHandlingContext); // Act var aggregateRoot = await repository.Get(knownIdentifier); // Assert aggregateRoot.Should().NotBeNull(); aggregateRoot.EventACount.Should().Be(2); aggregateRoot.EventBCount.Should().Be(1); }
public async Task Process_WithPrepareContextNotificationHandler_ShouldCallPrepareContextNotificationHandler() { // Arrange var serviceScopeMock = new Mock <IServiceScope>(); var serviceScopeFactoryMock = NewServiceScopeFactoryMock; serviceScopeFactoryMock.Setup(x => x.CreateScope()).Returns(() => serviceScopeMock.Object); var commandHandlingContext = new CommandHandlingContext(); serviceScopeMock .Setup(x => x.GetService(typeof(CommandHandlingContext))) .Returns(commandHandlingContext); serviceScopeMock .Setup(x => x.GetService(typeof(IEnumerable <ICommandHandler <FakeCommand> >))) .Returns(new[] { new Mock <ICommandHandler <FakeCommand> >().Object }); var command = new FakeCommand(); var prepareContextMock = new Mock <Action <object, CommandHandlingContext> >(); var notificationHandlers = new CommandProcessorNotificationHandlers { PrepareContext = prepareContextMock.Object }; var processor = new CommandProcessor(serviceScopeFactoryMock.Object, NewEventStoreMock.Object, NewEventDispatcherMock.Object, notificationHandlers); // Act await processor.Process(command); // Assert prepareContextMock.Verify(x => x(command, commandHandlingContext), Times.Once); prepareContextMock.Verify(x => x(It.IsAny <object>(), It.IsAny <CommandHandlingContext>()), Times.Once); }
public void Get_UnknownKey_ShouldReturnDefaultValue() { // Arrange var context = new CommandHandlingContext(); // Act / Assert context.Get <Test>("test").Should().BeNull(); context.Get <int>("test").Should().Be(0); }
public void CreateUnitOfWork_ShouldReturnUnitOfWork() { // Arrange var context = new CommandHandlingContext(); // Act var unitOfWork = context.CreateUnitOfWork <string, object>(); // Assert unitOfWork.Should().NotBeNull(); }
public void CreateUnitOfWork_ShouldSetCorrectProperty() { // Arrange var context = new CommandHandlingContext(); var unitOfWork = context.CreateUnitOfWork <string, object>(); // Act var unitOfWorkFromContext = context.Get <UnitOfWork <string, object> >(CommandHandlingContextExtensions.UnitOfWorkKey); // Assert unitOfWorkFromContext.Should().Be(unitOfWork); }
public void GetUnitOfWork_AfterSetUnitOfWork_ShouldReturnUnitOfWork() { // Arrange var context = new CommandHandlingContext(); var unitOfWork = context.CreateUnitOfWork <string, object>(); // Act var unitOfWorkFromContext = context.GetUnitOfWork <string, object>(); // Assert unitOfWorkFromContext.Should().Be(unitOfWork); }
public void GetUnitOfWork_WrongGenericType_ShouldThrowException() { // Arrange var context = new CommandHandlingContext(); var unitOfWork = context.CreateUnitOfWork <string, EventBase1>(); // Act / Assert Action action = () => context.GetUnitOfWork <string, EventBase2>(); action.Should().Throw <InvalidCastException>() .WithMessage($"Unable to cast object of type '{typeof(UnitOfWork<string, EventBase1>)}' to type '{typeof(UnitOfWork<string, EventBase2>)}'."); }
public void CreateUnitOfWork_TwiceOnSameContext_ShouldThrowException() { // Arrange var context = new CommandHandlingContext(); context.CreateUnitOfWork <string, object>(); // Act / Assert Action action = () => context.CreateUnitOfWork <string, object>(); action.Should().Throw <InvalidOperationException>() .WithMessage("Unit of work already created*"); }
public void Get_TypeMismatch_ShouldThrowException() { // Arrange var key = $"{Guid.NewGuid():N}"; var value = new Test(); var context = new CommandHandlingContext(); context.Set(key, value); // Act / Assert Action action = () => context.Get <int>(key); action.Should().Throw <InvalidCastException>(); }
public void SetGet_ShouldReturnValue() { // Arrange var key = $"{Guid.NewGuid():N}"; var value = new Test(); var context = new CommandHandlingContext(); // Act context.Set(key, value); var result = context.Get <Test>(key); // Assert result.Should().Be(value); }
public void Add_PassNullAsAggregateRoot_ShouldThrowException() { // Arrange var commandHandlingContext = new CommandHandlingContext(); commandHandlingContext.CreateUnitOfWork <string, object>(); var eventStoreMock = NewEventStoreMock; var repository = new Repository <FakeAggregateRoot>(eventStoreMock.Object, commandHandlingContext); // Act / Assert Func <Task> action = () => repository.Add("some_id", null); action.Should().Throw <ArgumentNullException>() .Which.ParamName.Should().Be("aggregateRoot"); }
public void OnPrepareContext_PrepareContextIsSet_ShouldCallPrepareContext() { // Arrange var command = new Mock <object>().Object; var context = new CommandHandlingContext(); var handlers = new CommandProcessorNotificationHandlers(); var handlerMock = new Mock <Action <object, CommandHandlingContext> >(); handlers.PrepareContext = handlerMock.Object; // Act handlers.OnPrepareContext(command, context); // Assert handlerMock.Verify(x => x(command, context), Times.Once); }
public void Add_AggregateRootAlreadyKnownByUnitOfWork_ShouldThrowException() { // Arrange var commandHandlingContext = new CommandHandlingContext(); var unitOfWork = commandHandlingContext.CreateUnitOfWork <string, object>(); var identifier = Guid.NewGuid().ToString("N"); var aggregateRoot = new FakeAggregateRoot(); unitOfWork.Attach(new AggregateRootEntity <string, object>(identifier, new FakeAggregateRoot(), 1)); var repository = new Repository <FakeAggregateRoot>(NewEventStoreMock.Object, commandHandlingContext); // Act / Assert Func <Task> action = () => repository.Add(identifier, aggregateRoot); action.Should().Throw <AggregateRootAlreadyExistsException <string> >() .WithMessage($"Exception for aggregate root with identifier '{identifier}': Aggregate root already attached"); }
public async Task Add_NewAggregateRoot_ShouldAttachToUnitOfWork() { // Arrange var commandHandlingContext = new CommandHandlingContext(); var unitOfWork = commandHandlingContext.CreateUnitOfWork <string, object>(); var identifier = Guid.NewGuid().ToString("N"); var aggregateRoot = new FakeAggregateRoot(); var repository = new Repository <FakeAggregateRoot>(NewEventStoreMock.Object, commandHandlingContext); // Act await repository.Add(identifier, aggregateRoot); // Assert unitOfWork.TryGet(identifier, out var aggregateRootEntityFromUnitOfWork).Should().BeTrue(); aggregateRootEntityFromUnitOfWork.Identifier.Should().Be(identifier); aggregateRootEntityFromUnitOfWork.AggregateRoot.Should().Be(aggregateRoot); }
public async Task Contains_KnownAggregateRoot_ShouldReturnTrue() { // Arrange var commandHandlingContext = new CommandHandlingContext(); commandHandlingContext.CreateUnitOfWork <string, object>(); var knownIdentifier = Guid.NewGuid().ToString("N"); var eventStoreMock = NewEventStoreMock; eventStoreMock.Setup(x => x.Contains(knownIdentifier)).ReturnsAsync(true); var repository = new Repository <FakeAggregateRoot>(eventStoreMock.Object, commandHandlingContext); // Act var result = await repository.Contains(knownIdentifier); // Assert result.Should().BeTrue(); }
public async Task Get_AggregateRootAlreadyAttachedToUnitOfWork_ShouldReturnAggregateRootFromUnitOfWork() { // Arrange var commandHandlingContext = new CommandHandlingContext(); var unitOfWork = commandHandlingContext.CreateUnitOfWork <string, object>(); var identifier = Guid.NewGuid().ToString("N"); var aggregateRoot = new FakeAggregateRoot(); unitOfWork.Attach(new AggregateRootEntity <string, object>(identifier, aggregateRoot, 1)); var eventStoreMock = NewEventStoreMock; var repository = new Repository <FakeAggregateRoot>(eventStoreMock.Object, commandHandlingContext); // Act var aggregateRootFromRepository = await repository.Get(identifier); // Assert aggregateRootFromRepository.Should().Be(aggregateRoot); eventStoreMock.Verify(x => x.GetEvents(identifier, 1), Times.Never); }
public async Task Process_ChangedAggregateRootsInUnitOfWork_ShouldCommitChangesToEventStore() { // Arrange var serviceScopeMock = new Mock <IServiceScope>(); var serviceScopeFactoryMock = NewServiceScopeFactoryMock; serviceScopeFactoryMock.Setup(x => x.CreateScope()).Returns(() => serviceScopeMock.Object); var commandHandlingContext = new CommandHandlingContext(); serviceScopeMock .Setup(x => x.GetService(typeof(CommandHandlingContext))) .Returns(commandHandlingContext); serviceScopeMock .Setup(x => x.GetService(typeof(IEnumerable <ICommandHandler <FakeCommand> >))) .Returns(new[] { new FakeCommandHandler(commandHandlingContext, x => x.DoSomething()) }); object[] capturedEvents = null; var transactionMock = new Mock <IEventStoreTransaction <string, object> >(); transactionMock .Setup(x => x.StoreEvents("some_id", 5, It.IsAny <IEnumerable <object> >(), default(CancellationToken))) #pragma warning disable IDE1006 // Naming Styles .Callback <string, long, IEnumerable <object>, CancellationToken>((_, __, events, ___) => capturedEvents = events.ToArray()) #pragma warning restore IDE1006 // Naming Styles .Returns(Task.CompletedTask); var eventStoreMock = NewEventStoreMock; eventStoreMock .Setup(x => x.BeginTransaction(It.IsAny <CommandHandlingContext>())) .Returns(transactionMock.Object); var processor = new CommandProcessor(serviceScopeFactoryMock.Object, eventStoreMock.Object, NewEventDispatcherMock.Object); // Act await processor.Process(new FakeCommand()); // Assert eventStoreMock.Verify(x => x.BeginTransaction(It.IsAny <CommandHandlingContext>()), Times.Once); capturedEvents.Should().NotBeNull(); capturedEvents.Should().HaveCount(2); capturedEvents[0].Should().BeOfType <FakeEvent2>(); capturedEvents[1].Should().BeOfType <FakeEvent1>(); transactionMock.Verify(x => x.Commit(), Times.Once); transactionMock.Verify(x => x.Rollback(), Times.Never); transactionMock.Verify(x => x.Dispose(), Times.Once); }
public void Add_AggregateRootAlreadyKnownByEventStore_ShouldThrowException() { // Arrange var commandHandlingContext = new CommandHandlingContext(); commandHandlingContext.CreateUnitOfWork <string, object>(); var identifier = Guid.NewGuid().ToString("N"); var aggregateRoot = new FakeAggregateRoot(); var eventStoreMock = NewEventStoreMock; eventStoreMock.Setup(x => x.Contains(identifier)).ReturnsAsync(true); var repository = new Repository <FakeAggregateRoot>(eventStoreMock.Object, commandHandlingContext); // Act / Assert Func <Task> action = () => repository.Add(identifier, aggregateRoot); action.Should().Throw <AggregateRootAlreadyExistsException <string> >() .WithMessage($"Exception for aggregate root with identifier '{identifier}': Aggregate root already attached"); }
public async Task Contains_NewAggregateRootAttachedToUnitOfWork_ShouldReturnTrue() { // Arrange var commandHandlingContext = new CommandHandlingContext(); commandHandlingContext.CreateUnitOfWork <string, object>(); var newIdentifier = Guid.NewGuid().ToString("N"); var aggregateRoot = new FakeAggregateRoot(); var unitOfWork = commandHandlingContext.GetUnitOfWork <string, object>(); unitOfWork.Attach(new AggregateRootEntity <string, object>(newIdentifier, aggregateRoot, 1)); var repository = new Repository <FakeAggregateRoot>(NewEventStoreMock.Object, commandHandlingContext); // Act var result = await repository.Contains(newIdentifier); // Assert result.Should().BeTrue(); }
public void OnEnrichEvent_EnrichEventIsSet_ShouldCallEnrichEvent() { // Arrange var @event = new Mock <object>().Object; var command = new Mock <object>().Object; var enrichedEvent = new Mock <object>().Object; var context = new CommandHandlingContext(); var handlers = new CommandProcessorNotificationHandlers(); var handlerMock = new Mock <Func <object, object, CommandHandlingContext, object> >(); handlerMock.Setup(x => x(@event, command, context)).Returns(enrichedEvent); handlers.EnrichEvent = handlerMock.Object; // Act var result = handlers.OnEnrichEvent(@event, command, context); // Assert handlerMock.Verify(x => x(@event, command, context), Times.Once); result.Should().Be(enrichedEvent); }
public async Task Process_ChangedAggregateRootsInUnitOfWork_ShouldDispatchEvents() { // Arrange var serviceScopeMock = new Mock <IServiceScope>(); var serviceScopeFactoryMock = NewServiceScopeFactoryMock; serviceScopeFactoryMock.Setup(x => x.CreateScope()).Returns(() => serviceScopeMock.Object); var commandHandlingContext = new CommandHandlingContext(); serviceScopeMock .Setup(x => x.GetService(typeof(CommandHandlingContext))) .Returns(commandHandlingContext); serviceScopeMock .Setup(x => x.GetService(typeof(IEnumerable <ICommandHandler <FakeCommand> >))) .Returns(new[] { new FakeCommandHandler(commandHandlingContext, x => x.DoSomething()) }); object[] dispatchedEvents = null; var eventDispatcherMock = NewEventDispatcherMock; eventDispatcherMock .Setup(x => x.Dispatch(It.IsAny <object[]>(), default(CancellationToken))) .Callback <object[], CancellationToken>((events, _) => dispatchedEvents = events) .Returns(Task.CompletedTask); var transactionMock = new Mock <IEventStoreTransaction <string, object> >(); var eventStoreMock = NewEventStoreMock; eventStoreMock .Setup(x => x.BeginTransaction(It.IsAny <CommandHandlingContext>())) .Returns(transactionMock.Object); var processor = new CommandProcessor(serviceScopeFactoryMock.Object, eventStoreMock.Object, eventDispatcherMock.Object); // Act await processor.Process(new FakeCommand()); // Assert eventDispatcherMock.Verify(x => x.Dispatch(It.IsAny <object[]>(), default(CancellationToken)), Times.Once); dispatchedEvents.Should().NotBeNull(); dispatchedEvents.Should().HaveCount(2); dispatchedEvents[0].Should().BeOfType <FakeEvent2>(); dispatchedEvents[1].Should().BeOfType <FakeEvent1>(); }
public void Process_DispatchThrowsException_ShouldRollbackTransactionAndRethrowException() { // Arrange var serviceScopeMock = new Mock <IServiceScope>(); var serviceScopeFactoryMock = NewServiceScopeFactoryMock; serviceScopeFactoryMock.Setup(x => x.CreateScope()).Returns(() => serviceScopeMock.Object); var commandHandlingContext = new CommandHandlingContext(); serviceScopeMock .Setup(x => x.GetService(typeof(CommandHandlingContext))) .Returns(commandHandlingContext); serviceScopeMock .Setup(x => x.GetService(typeof(IEnumerable <ICommandHandler <FakeCommand> >))) .Returns(new[] { new FakeCommandHandler(commandHandlingContext, x => x.DoSomething()) }); var eventDispatcherMock = NewEventDispatcherMock; eventDispatcherMock .Setup(x => x.Dispatch(It.IsAny <object[]>(), default(CancellationToken))) .Callback(() => throw new InvalidOperationException("Dispatch failed")); var transactionMock = new Mock <IEventStoreTransaction <string, object> >(); var eventStoreMock = NewEventStoreMock; eventStoreMock .Setup(x => x.BeginTransaction(It.IsAny <CommandHandlingContext>())) .Returns(transactionMock.Object); var processor = new CommandProcessor(serviceScopeFactoryMock.Object, eventStoreMock.Object, eventDispatcherMock.Object); // Act / Assert Func <Task> action = () => processor.Process(new FakeCommand()); action.Should().Throw <InvalidOperationException>() .WithMessage("Dispatch failed"); eventStoreMock.Verify(x => x.BeginTransaction(It.IsAny <CommandHandlingContext>()), Times.Once); transactionMock.Verify(x => x.Commit(), Times.Never); transactionMock.Verify(x => x.Rollback(), Times.Once); transactionMock.Verify(x => x.Dispose(), Times.Once); }
public async Task Get_KnownAggregateRoot_ShouldAttachAggregateRootEntityToUnitOfWork() { // Arrange var commandHandlingContext = new CommandHandlingContext(); var unitOfWork = commandHandlingContext.CreateUnitOfWork <string, object>(); var knownIdentifier = Guid.NewGuid().ToString("N"); var eventStoreMock = NewEventStoreMock; eventStoreMock.Setup(x => x.GetEvents(knownIdentifier, 0)).ReturnsAsync(new object[] { new EventA(), new EventB(), }); var repository = new Repository <FakeAggregateRoot>(eventStoreMock.Object, commandHandlingContext); // Act var aggregateRootFromRepository = await repository.Get(knownIdentifier); // Assert unitOfWork.TryGet(knownIdentifier, out var aggregateRootEntityFromUnitOfWork).Should().BeTrue(); aggregateRootEntityFromUnitOfWork.Identifier.Should().Be(knownIdentifier); aggregateRootEntityFromUnitOfWork.AggregateRoot.Should().Be(aggregateRootFromRepository); eventStoreMock.Verify(x => x.GetEvents(knownIdentifier, 0), Times.Once); }
public FakeCommandHandler(CommandHandlingContext context, Action <FakeAggregateRoot> action) { _context = context; _action = action; }
public async Task Process_WithEnrichEventNotificationHandler_ShouldCallEnrichEventNotificationHandler() { // Arrange object capturedEvent1 = null; object capturedEvent2 = null; IEnumerable <object> capturedStoredEvents = null; var serviceScopeMock = new Mock <IServiceScope>(); var serviceScopeFactoryMock = NewServiceScopeFactoryMock; serviceScopeFactoryMock.Setup(x => x.CreateScope()).Returns(() => serviceScopeMock.Object); var commandHandlingContext = new CommandHandlingContext(); serviceScopeMock .Setup(x => x.GetService(typeof(CommandHandlingContext))) .Returns(commandHandlingContext); serviceScopeMock .Setup(x => x.GetService(typeof(IEnumerable <ICommandHandler <FakeCommand> >))) .Returns(new[] { new FakeCommandHandler(commandHandlingContext, x => x.DoSomething()) }); var transactionMock = new Mock <IEventStoreTransaction <string, object> >(); var eventStoreMock = NewEventStoreMock; eventStoreMock .Setup(x => x.BeginTransaction(It.IsAny <CommandHandlingContext>())) .Returns(transactionMock.Object); transactionMock .Setup(x => x.StoreEvents("some_id", 5, It.IsAny <IEnumerable <object> >(), default(CancellationToken))) .Callback <string, long, IEnumerable <object>, CancellationToken>((_, __, x, ___) => capturedStoredEvents = x) .Returns(Task.CompletedTask); var command = new FakeCommand(); var event1 = new FakeEvent1(); var event2 = new FakeEvent2(); var enrichEventMock = new Mock <Func <object, object, CommandHandlingContext, object> >(); enrichEventMock .Setup(x => x(It.Is <object>(y => y is FakeEvent1), command, It.IsAny <CommandHandlingContext>())) .Callback <object, object, CommandHandlingContext>((x, _, __) => capturedEvent1 = x) .Returns(event1); enrichEventMock .Setup(x => x(It.Is <object>(y => y is FakeEvent2), command, It.IsAny <CommandHandlingContext>())) .Callback <object, object, CommandHandlingContext>((x, _, __) => capturedEvent2 = x) .Returns(event2); var notificationHandlers = new CommandProcessorNotificationHandlers { EnrichEvent = enrichEventMock.Object }; var processor = new CommandProcessor(serviceScopeFactoryMock.Object, eventStoreMock.Object, NewEventDispatcherMock.Object, notificationHandlers); // Act await processor.Process(command); // Assert capturedEvent1.Should().NotBeNull(); capturedEvent2.Should().NotBeNull(); capturedStoredEvents.Should().NotBeNull(); enrichEventMock.Verify(x => x(capturedEvent1, command, commandHandlingContext), Times.Once); enrichEventMock.Verify(x => x(capturedEvent2, command, commandHandlingContext), Times.Once); transactionMock.Verify(x => x.StoreEvents("some_id", 5, capturedStoredEvents, default(CancellationToken)), Times.Once); capturedStoredEvents.Should().Contain(event1); capturedStoredEvents.Should().Contain(event2); }
/// <summary> /// Creates a new <see cref="Repository{TAggregateRoot}"/> instance. /// </summary> /// <param name="eventStore">The event store.</param> /// <param name="commandHandlingContext">The command handling context.</param> public Repository(IEventStore <string, object> eventStore, CommandHandlingContext commandHandlingContext) : base(eventStore, commandHandlingContext) { }