// ========================================================================== // AggregateHandlerTests.cs // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex Group // All rights reserved. // ========================================================================== using System; using System.Collections.Generic; using System.Threading.Tasks; using FakeItEasy; using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.Tasks; using Xunit; namespace Squidex.Infrastructure.CQRS.Commands { public class AggregateHandlerTests { private sealed class MyEvent : IEvent { } private sealed class MyCommand : IAggregateCommand { public Guid AggregateId { get; set; } public long? ExpectedVersion { get; set; } } private sealed class MyDomainObject : DomainObjectBase { public MyDomainObject(Guid id, int version) : base(id, version) { } public MyDomainObject RaiseNewEvent(Envelope @event) { RaiseEvent(@event); return this; } protected override void DispatchEvent(Envelope @event) { } } private readonly IDomainObjectFactory factory = A.Fake(); private readonly IDomainObjectRepository repository = A.Fake(); private readonly Envelope event1 = new Envelope(new MyEvent()); private readonly Envelope event2 = new Envelope(new MyEvent()); private readonly CommandContext context; private readonly MyCommand command; private readonly AggregateHandler sut; private readonly MyDomainObject domainObject; public AggregateHandlerTests() { sut = new AggregateHandler(factory, repository); domainObject = new MyDomainObject(Guid.NewGuid(), 1) .RaiseNewEvent(event1) .RaiseNewEvent(event2); command = new MyCommand { AggregateId = domainObject.Id }; context = new CommandContext(command); } [Fact] public void Should_provide_access_to_factory() { Assert.Equal(factory, sut.Factory); } [Fact] public void Should_provide_access_to_repository() { Assert.Equal(repository, sut.Repository); } [Fact] public Task Create_async_should_throw_exception_if_not_aggregate_command() { return Assert.ThrowsAnyAsync(() => sut.CreateAsync(new CommandContext(A.Dummy()), x => TaskHelper.False)); } [Fact] public async Task Create_async_should_create_domain_object_and_save() { A.CallTo(() => factory.CreateNew(typeof(MyDomainObject), domainObject.Id)) .Returns(domainObject); A.CallTo(() => repository.SaveAsync(domainObject, A>>.Ignored, A.Ignored)) .Returns(TaskHelper.Done); MyDomainObject passedDomainObject = null; await sut.CreateAsync(context, async x => { await Task.Delay(1); passedDomainObject = x; }); Assert.Equal(domainObject, passedDomainObject); Assert.NotNull(context.Result>()); A.CallTo(() => repository.SaveAsync(domainObject, A>>.Ignored, A.Ignored)).MustHaveHappened(); } [Fact] public async Task Create_sync_should_create_domain_object_and_save() { A.CallTo(() => factory.CreateNew(typeof(MyDomainObject), domainObject.Id)) .Returns(domainObject); A.CallTo(() => repository.SaveAsync(domainObject, A>>.Ignored, A.Ignored)) .Returns(TaskHelper.Done); MyDomainObject passedDomainObject = null; await sut.CreateAsync(context, x => { passedDomainObject = x; }); Assert.Equal(domainObject, passedDomainObject); Assert.NotNull(context.Result>()); A.CallTo(() => repository.SaveAsync(domainObject, A>>.Ignored, A.Ignored)).MustHaveHappened(); } [Fact] public Task Update_async_should_throw_exception_if_not_aggregate_command() { return Assert.ThrowsAnyAsync(() => sut.UpdateAsync(new CommandContext(A.Dummy()), x => TaskHelper.False)); } [Fact] public async Task Update_async_should_create_domain_object_and_save() { A.CallTo(() => repository.GetByIdAsync(command.AggregateId, null)) .Returns(Task.FromResult(domainObject)); A.CallTo(() => repository.SaveAsync(domainObject, A>>.Ignored, A.Ignored)) .Returns(TaskHelper.Done); MyDomainObject passedDomainObject = null; await sut.UpdateAsync(context, async x => { await Task.Delay(1); passedDomainObject = x; }); Assert.Equal(domainObject, passedDomainObject); Assert.NotNull(context.Result()); A.CallTo(() => repository.SaveAsync(domainObject, A>>.Ignored, A.Ignored)).MustHaveHappened(); } [Fact] public async Task Update_sync_should_create_domain_object_and_save() { A.CallTo(() => repository.GetByIdAsync(command.AggregateId, null)) .Returns(Task.FromResult(domainObject)); A.CallTo(() => repository.SaveAsync(domainObject, A>>.Ignored, A.Ignored)) .Returns(TaskHelper.Done); MyDomainObject passedDomainObject = null; await sut.UpdateAsync(context, x => { passedDomainObject = x; }); Assert.Equal(domainObject, passedDomainObject); Assert.NotNull(context.Result()); A.CallTo(() => repository.SaveAsync(domainObject, A>>.Ignored, A.Ignored)).MustHaveHappened(); } } }