Browse Source

Some more tests

pull/1/head
Sebastian 9 years ago
parent
commit
63d06afc6c
  1. 28
      src/PinkParrot.Infrastructure/CQRS/Commands/CommandHandler.cs
  2. 2
      src/PinkParrot.Infrastructure/CQRS/Commands/ICommandBus.cs
  3. 4
      src/PinkParrot.Infrastructure/CQRS/Commands/InMemoryCommandBus.cs
  4. 5
      src/PinkParrot.Infrastructure/PropertyValue.cs
  5. 129
      tests/PinkParrot.Infrastructure.Tests/CQRS/Commands/CommandsHandlerTests.cs
  6. 116
      tests/PinkParrot.Infrastructure.Tests/CQRS/Commands/InMemoryCommandBusTests.cs
  7. 82
      tests/PinkParrot.Infrastructure.Tests/CQRS/EnvelopeExtensionsTests.cs
  8. 18
      tests/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs
  9. 5
      tests/PinkParrot.Infrastructure.Tests/project.json

28
src/PinkParrot.Infrastructure/CQRS/Commands/CommandHandler.cs

@ -49,14 +49,11 @@ namespace PinkParrot.Infrastructure.CQRS.Commands
protected Task CreateAsync(IAggregateCommand command, Action<T> creator) protected Task CreateAsync(IAggregateCommand command, Action<T> creator)
{ {
Guard.NotNull(creator, nameof(creator)); return CreateAsync(command, x =>
Guard.NotNull(command, nameof(command)); {
creator(x);
var domainObject = domainObjectFactory.CreateNew<T>(command.AggregateId); return Task.FromResult(true);
});
creator(domainObject);
return domainObjectRepository.SaveAsync(domainObject, command.AggregateId);
} }
protected async Task UpdateAsync(IAggregateCommand command, Func<T, Task> updater) protected async Task UpdateAsync(IAggregateCommand command, Func<T, Task> updater)
@ -71,16 +68,13 @@ namespace PinkParrot.Infrastructure.CQRS.Commands
await domainObjectRepository.SaveAsync(domainObject, Guid.NewGuid()); await domainObjectRepository.SaveAsync(domainObject, Guid.NewGuid());
} }
protected async Task UpdateAsync(IAggregateCommand command, Action<T> updater) protected Task UpdateAsync(IAggregateCommand command, Action<T> updater)
{ {
Guard.NotNull(updater, nameof(updater)); return UpdateAsync(command, x =>
Guard.NotNull(command, nameof(command)); {
updater(x);
var domainObject = await domainObjectRepository.GetByIdAsync<T>(command.AggregateId); return Task.FromResult(true);
});
updater(domainObject);
await domainObjectRepository.SaveAsync(domainObject, Guid.NewGuid());
} }
public abstract Task<bool> HandleAsync(CommandContext context); public abstract Task<bool> HandleAsync(CommandContext context);

2
src/PinkParrot.Infrastructure/CQRS/Commands/ICommandBus.cs

@ -12,6 +12,6 @@ namespace PinkParrot.Infrastructure.CQRS.Commands
{ {
public interface ICommandBus public interface ICommandBus
{ {
Task PublishAsync(ICommand command); Task<CommandContext> PublishAsync(ICommand command);
} }
} }

4
src/PinkParrot.Infrastructure/CQRS/Commands/InMemoryCommandBus.cs

@ -23,7 +23,7 @@ namespace PinkParrot.Infrastructure.CQRS.Commands
this.handlers = handlers; this.handlers = handlers;
} }
public async Task PublishAsync(ICommand command) public async Task<CommandContext> PublishAsync(ICommand command)
{ {
Guard.NotNull(command, nameof(command)); Guard.NotNull(command, nameof(command));
@ -50,6 +50,8 @@ namespace PinkParrot.Infrastructure.CQRS.Commands
{ {
throw context.Exception; throw context.Exception;
} }
return context;
} }
} }
} }

5
src/PinkParrot.Infrastructure/PropertyValue.cs

@ -58,11 +58,6 @@ namespace PinkParrot.Infrastructure
{ {
result = null; result = null;
if (binder.Type == typeof(object))
{
result = rawValue;
}
Func<PropertyValue, CultureInfo, object> parser; Func<PropertyValue, CultureInfo, object> parser;
if (!Parsers.TryGetValue(binder.Type, out parser)) if (!Parsers.TryGetValue(binder.Type, out parser))

129
tests/PinkParrot.Infrastructure.Tests/CQRS/Commands/CommandsHandlerTests.cs

@ -0,0 +1,129 @@
// ==========================================================================
// CommandsHandlerTests.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
using System.Threading.Tasks;
using Moq;
using PinkParrot.Infrastructure.CQRS.Events;
using Xunit;
namespace PinkParrot.Infrastructure.CQRS.Commands
{
public class CommandsHandlerTests
{
private readonly Mock<IDomainObjectFactory> domainObjectFactory = new Mock<IDomainObjectFactory>();
private readonly Mock<IDomainObjectRepository> domainObjectRepository = new Mock<IDomainObjectRepository>();
private readonly TestCommandHandler sut;
private readonly Guid id = Guid.NewGuid();
private sealed class TestCommand : AggregateCommand
{
}
private sealed class TestDomainObject : DomainObject
{
public TestDomainObject(Guid id, int version) : base(id, version)
{
}
protected override void DispatchEvent(Envelope<IEvent> @event)
{
throw new NotImplementedException();
}
}
private sealed class TestCommandHandler : CommandHandler<TestDomainObject>
{
public TestCommandHandler(IDomainObjectFactory domainObjectFactory, IDomainObjectRepository domainObjectRepository)
: base(domainObjectFactory, domainObjectRepository)
{
}
public override Task<bool> HandleAsync(CommandContext context)
{
throw new NotImplementedException();
}
public IDomainObjectFactory TestFactory
{
get { return Factory; }
}
public IDomainObjectRepository TestRepository
{
get { return Repository; }
}
public Task CreateTestAsync(IAggregateCommand command, Action<TestDomainObject> creator)
{
return CreateAsync(command, creator);
}
public Task UpdateTestAsync(IAggregateCommand command, Action<TestDomainObject> updater)
{
return UpdateAsync(command, updater);
}
}
public CommandsHandlerTests()
{
sut = new TestCommandHandler(domainObjectFactory.Object, domainObjectRepository.Object);
}
[Fact]
public void Should_provide_factory()
{
Assert.Equal(domainObjectFactory.Object, sut.TestFactory);
}
[Fact]
public void Should_provide_repository()
{
Assert.Equal(domainObjectRepository.Object, sut.TestRepository);
}
[Fact]
public async Task Should_retrieve_from_repository_and_update()
{
var command = new TestCommand { AggregateId = id };
var domainObject = new TestDomainObject(id, 123);
domainObjectRepository.Setup(x => x.GetByIdAsync<TestDomainObject>(id, int.MaxValue)).Returns(Task.FromResult(domainObject)).Verifiable();
domainObjectRepository.Setup(x => x.SaveAsync(domainObject, It.IsAny<Guid>())).Returns(Task.FromResult(true)).Verifiable();
var isCalled = false;
await sut.UpdateTestAsync(command, x => isCalled = true);
domainObjectRepository.VerifyAll();
Assert.True(isCalled);
}
[Fact]
public async Task Should_create_with_factory_and_update()
{
var command = new TestCommand { AggregateId = id };
var domainObject = new TestDomainObject(id, 123);
domainObjectFactory.Setup(x => x.CreateNew(typeof(TestDomainObject), id)).Returns(domainObject).Verifiable();
domainObjectRepository.Setup(x => x.SaveAsync(domainObject, It.IsAny<Guid>())).Returns(Task.FromResult(true)).Verifiable();
var isCalled = false;
await sut.CreateTestAsync(command, x => isCalled = true);
domainObjectFactory.VerifyAll();
domainObjectRepository.VerifyAll();
Assert.True(isCalled);
}
}
}

116
tests/PinkParrot.Infrastructure.Tests/CQRS/Commands/InMemoryCommandBusTests.cs

@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace PinkParrot.Infrastructure.CQRS.Commands
{
public class InMemoryCommandBusTests
{
private readonly TestCommand command = new TestCommand();
private sealed class TestCommand : ICommand
{
}
private sealed class HandledHandler : ICommandHandler
{
public ICommand LastCommand;
public Task<bool> HandleAsync(CommandContext context)
{
LastCommand = context.Command;
return Task.FromResult(true);
}
}
private sealed class NonHandledHandler : ICommandHandler
{
public ICommand LastCommand;
public Task<bool> HandleAsync(CommandContext context)
{
LastCommand = context.Command;
return Task.FromResult(false);
}
}
private sealed class ThrowHandledHandler : ICommandHandler
{
public ICommand LastCommand;
public Task<bool> HandleAsync(CommandContext context)
{
LastCommand = context.Command;
throw new InvalidOperationException();
}
}
private sealed class AfterThrowHandler : ICommandHandler
{
public Exception LastException;
public Task<bool> HandleAsync(CommandContext context)
{
LastException = context.Exception;
return Task.FromResult(false);
}
}
[Fact]
public async Task Should_not_set_handled_if_no_handler_registered()
{
var sut = new InMemoryCommandBus(new ICommandHandler[0]);
var ctx = await sut.PublishAsync(command);
Assert.False(ctx.IsHandled);
}
[Fact]
public async Task Should_not_set_succeeded_if_handler_returns_false()
{
var handler = new NonHandledHandler();
var sut = new InMemoryCommandBus(new ICommandHandler[] { handler });
var ctx = await sut.PublishAsync(command);
Assert.Equal(command, handler.LastCommand);
Assert.False(ctx.IsSucceeded);
Assert.False(ctx.IsHandled);
Assert.Null(ctx.Exception);
}
[Fact]
public async Task Should_set_succeeded_if_handler_returns_true()
{
var handler = new HandledHandler();
var sut = new InMemoryCommandBus(new ICommandHandler[] { handler });
var ctx = await sut.PublishAsync(command);
Assert.Equal(command, handler.LastCommand);
Assert.True(ctx.IsSucceeded);
Assert.True(ctx.IsHandled);
Assert.Null(ctx.Exception);
}
[Fact]
public async Task Should_throw_and_call_all_handlers_if_first_handler_fails()
{
var handler1 = new ThrowHandledHandler();
var handler2 = new AfterThrowHandler();
var sut = new InMemoryCommandBus(new ICommandHandler[] { handler1, handler2 });
await Assert.ThrowsAsync<InvalidOperationException>(async () => await sut.PublishAsync(command));
Assert.Equal(command, handler1.LastCommand);
Assert.IsType<InvalidOperationException>(handler2.LastException);
}
}
}

82
tests/PinkParrot.Infrastructure.Tests/CQRS/EnvelopeExtensionsTests.cs

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using NodaTime;
using Xunit;
namespace PinkParrot.Infrastructure.CQRS
{
public class EnvelopeExtensionsTests
{
private readonly Envelope<string> sut = new Envelope<string>(string.Empty);
private readonly CultureInfo culture = CultureInfo.InvariantCulture;
[Fact]
public void Should_set_and_get_timestamp()
{
var timestamp = SystemClock.Instance.GetCurrentInstant();
sut.SetTimestamp(timestamp);
Assert.Equal(timestamp, sut.Headers.Timestamp());
Assert.Equal(timestamp, sut.Headers["Timestamp"].ToInstant(culture));
}
[Fact]
public void Should_set_and_get_commit_id()
{
var commitId = Guid.NewGuid();
sut.SetCommitId(commitId);
Assert.Equal(commitId, sut.Headers.CommitId());
Assert.Equal(commitId, sut.Headers["CommitId"].ToGuid(culture));
}
[Fact]
public void Should_set_and_get_event_id()
{
var commitId = Guid.NewGuid();
sut.SetEventId(commitId);
Assert.Equal(commitId, sut.Headers.EventId());
Assert.Equal(commitId, sut.Headers["EventId"].ToGuid(culture));
}
[Fact]
public void Should_set_and_get_aggregate_id()
{
var commitId = Guid.NewGuid();
sut.SetAggregateId(commitId);
Assert.Equal(commitId, sut.Headers.AggregateId());
Assert.Equal(commitId, sut.Headers["AggregateId"].ToGuid(culture));
}
[Fact]
public void Should_set_and_get_app_id()
{
var commitId = Guid.NewGuid();
sut.SetAppId(commitId);
Assert.Equal(commitId, sut.Headers.AppId());
Assert.Equal(commitId, sut.Headers["AppId"].ToGuid(culture));
}
[Fact]
public void Should_set_and_get_event_number()
{
const int eventNumber = 123;
sut.SetEventNumber(eventNumber);
Assert.Equal(eventNumber, sut.Headers.EventNumber());
Assert.Equal(eventNumber, sut.Headers["EventNumber"].ToInt32(culture));
}
}
}

18
tests/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs

@ -7,8 +7,10 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Dynamic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using Microsoft.CSharp.RuntimeBinder;
using Newtonsoft.Json; using Newtonsoft.Json;
using NodaTime; using NodaTime;
using PinkParrot.Infrastructure.Json; using PinkParrot.Infrastructure.Json;
@ -181,6 +183,22 @@ namespace PinkParrot.Infrastructure
Assert.Equal(0, (int)dynamicBag.Key); Assert.Equal(0, (int)dynamicBag.Key);
} }
[Fact]
public void Should_throw_when_parsing_failed()
{
bag.Set("Key", "abc");
Assert.Throws<InvalidCastException>(() => bag["Key"].ToInt32(CultureInfo.InvariantCulture));
}
[Fact]
public void Should_return_false_when_converter_does_not_exist()
{
bag.Set("Key", "abc");
Assert.Throws<RuntimeBinderException>(() => (TimeSpan)dynamicBag.Key);
}
[Fact] [Fact]
public void Should_convert_string_to_numbers() public void Should_convert_string_to_numbers()
{ {

5
tests/PinkParrot.Infrastructure.Tests/project.json

@ -8,6 +8,8 @@
}, },
"dependencies": { "dependencies": {
"dotnet-test-xunit": "2.2.0-preview2-build1029", "dotnet-test-xunit": "2.2.0-preview2-build1029",
"Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final",
"Moq": "4.6.38-alpha",
"PinkParrot.Infrastructure": "1.0.0-*", "PinkParrot.Infrastructure": "1.0.0-*",
"xunit": "2.2.0-beta3-build3402" "xunit": "2.2.0-beta3-build3402"
}, },
@ -25,5 +27,8 @@
"tooling": { "tooling": {
"defaultNamespace": "PinkParrot.Core.Tests" "defaultNamespace": "PinkParrot.Core.Tests"
}, },
"tools": {
"Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final"
},
"version": "1.0.0-*" "version": "1.0.0-*"
} }
Loading…
Cancel
Save