-
-
Notifications
You must be signed in to change notification settings - Fork 448
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
537 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
326 changes: 326 additions & 0 deletions
326
Source/EventFlow.Tests/UnitTests/Sagas/AggregateSagas/AggregateSagaTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,326 @@ | ||
using EventFlow.Aggregates; | ||
using EventFlow.Aggregates.ExecutionResults; | ||
using EventFlow.Commands; | ||
using EventFlow.Exceptions; | ||
using EventFlow.Sagas; | ||
using EventFlow.TestHelpers; | ||
using EventFlow.TestHelpers.Aggregates; | ||
using EventFlow.TestHelpers.Aggregates.Commands; | ||
using EventFlow.TestHelpers.Aggregates.Events; | ||
using EventFlow.TestHelpers.Aggregates.Sagas; | ||
using FluentAssertions; | ||
using Moq; | ||
using NUnit.Framework; | ||
using System; | ||
using System.Reflection; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace EventFlow.Tests.UnitTests.Sagas.AggregateSagas | ||
{ | ||
[Category(Categories.Unit)] | ||
public class AggregateSagaTests : TestsFor<ThingySaga> | ||
{ | ||
private ThingySagaId _thingySagaId; | ||
private Mock<ICommandBus> _commandBus; | ||
private Mock<ISagaContext> _sagaContext; | ||
|
||
[SetUp] | ||
public async Task SetUp() | ||
{ | ||
_thingySagaId = A<ThingySagaId>(); | ||
_commandBus = InjectMock<ICommandBus>(); | ||
_sagaContext = InjectMock<ISagaContext>(); | ||
|
||
await Sut.HandleAsync( | ||
A<DomainEvent<ThingyAggregate, ThingyId, ThingySagaStartRequestedEvent>>(), | ||
_sagaContext.Object, | ||
CancellationToken.None); | ||
} | ||
|
||
[Test] | ||
public async Task AggregateSaga_PublishAsync_ExecutionResultIsSuccessTrueDoesNotThrow() | ||
{ | ||
// Arrange | ||
_commandBus.Setup( | ||
a => a.PublishAsync( | ||
It.IsAny<ICommand<ThingyAggregate, ThingyId, IExecutionResult>>(), | ||
It.IsAny<CancellationToken>())) | ||
.Returns(() => Task.FromResult(ExecutionResult.Success())); | ||
await Sut.HandleAsync( | ||
A<DomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent>>(), | ||
_sagaContext.Object, | ||
CancellationToken.None); | ||
var exception = (Exception)null; | ||
|
||
// Act | ||
try | ||
{ | ||
await Sut.PublishAsync( | ||
_commandBus.Object, | ||
CancellationToken.None); | ||
} | ||
catch (Exception e) | ||
{ | ||
exception = e; | ||
} | ||
|
||
// Assert | ||
exception.Should().BeNull(); | ||
} | ||
|
||
[Test] | ||
public async Task AggregateSaga_PublishAsync_ExecutionResultIsNullDoesNotThrow() | ||
{ | ||
// Arrange | ||
_commandBus.Setup( | ||
a => a.PublishAsync( | ||
It.IsAny<ICommand<ThingyAggregate, ThingyId, IExecutionResult>>(), | ||
It.IsAny<CancellationToken>())) | ||
.Returns(() => Task.FromResult<IExecutionResult>(null)); | ||
await Sut.HandleAsync( | ||
A<DomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent>>(), | ||
_sagaContext.Object, | ||
CancellationToken.None); | ||
var exception = (Exception)null; | ||
|
||
// Act | ||
try | ||
{ | ||
await Sut.PublishAsync( | ||
_commandBus.Object, | ||
CancellationToken.None); | ||
} | ||
catch (Exception e) | ||
{ | ||
exception = e; | ||
} | ||
|
||
// Assert | ||
exception.Should().BeNull(); | ||
} | ||
|
||
[Test] | ||
public async Task AggregateSaga_PublishAsync_ExecutionResultIsSuccessFalseDisableThrow() | ||
{ | ||
// Arrange | ||
Sut.GetType() | ||
.GetProperty("ThrowExceptionsOnFailedPublish", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty) | ||
.SetValue(Sut, false); | ||
var message = Guid.NewGuid().ToString(); | ||
_commandBus.Setup( | ||
a => a.PublishAsync( | ||
It.IsAny<ICommand<ThingyAggregate, ThingyId, IExecutionResult>>(), | ||
It.IsAny<CancellationToken>())) | ||
.Returns(() => Task.FromResult(ExecutionResult.Failed(message))); | ||
await Sut.HandleAsync( | ||
A<DomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent>>(), | ||
_sagaContext.Object, | ||
CancellationToken.None); | ||
var exception = (Exception)null; | ||
|
||
// Act | ||
try | ||
{ | ||
await Sut.PublishAsync( | ||
_commandBus.Object, | ||
CancellationToken.None); | ||
} | ||
catch (Exception e) | ||
{ | ||
exception = e; | ||
} | ||
|
||
// Assert | ||
exception.Should().BeNull(); | ||
} | ||
|
||
[Test] | ||
public async Task AggregateSaga_PublishAsync_ExecutionResultIsSuccessFalseThrows() | ||
{ | ||
// Arrange | ||
var message = Guid.NewGuid().ToString(); | ||
_commandBus.Setup( | ||
a => a.PublishAsync( | ||
It.IsAny<ICommand<ThingyAggregate, ThingyId, IExecutionResult>>(), | ||
It.IsAny<CancellationToken>())) | ||
.Returns(() => Task.FromResult(ExecutionResult.Failed(message))); | ||
await Sut.HandleAsync( | ||
A<DomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent>>(), | ||
_sagaContext.Object, | ||
CancellationToken.None); | ||
var exception = (Exception)null; | ||
|
||
// Act | ||
try | ||
{ | ||
await Sut.PublishAsync( | ||
_commandBus.Object, | ||
CancellationToken.None); | ||
} | ||
catch (Exception e) | ||
{ | ||
exception = e; | ||
} | ||
|
||
// Assert | ||
exception.Should().NotBeNull(); | ||
exception.Should().BeAssignableTo<SagaPublishException>(); | ||
var sagaPublishException = exception as SagaPublishException; | ||
sagaPublishException.InnerExceptions.Count.Should().Be(1); | ||
var innerException = sagaPublishException.InnerExceptions[0]; | ||
innerException.Should().BeAssignableTo<CommandException>(); | ||
var commandException = innerException as CommandException; | ||
commandException.Message.Should().Contain(message); | ||
commandException.Message.Should().Contain(Sut.Id.ToString()); | ||
commandException.CommandType.Should().Be(typeof(ThingyAddMessageCommand)); | ||
commandException.ExecutionResult.Should().NotBeNull(); | ||
commandException.ExecutionResult.IsSuccess.Should().BeFalse(); | ||
commandException.ExecutionResult.ToString().Should().Contain(message); | ||
} | ||
|
||
[Test] | ||
public async Task AggregateSaga_PublishAsync_ExecutionResultIsSuccessFalseThrowsTwice() | ||
{ | ||
// Arrange | ||
var message = Guid.NewGuid().ToString(); | ||
_commandBus.Setup( | ||
a => a.PublishAsync( | ||
It.IsAny<ICommand<ThingyAggregate, ThingyId, IExecutionResult>>(), | ||
It.IsAny<CancellationToken>())) | ||
.Returns(() => Task.FromResult(ExecutionResult.Failed(message))); | ||
await Sut.HandleAsync( | ||
A<DomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent>>(), | ||
_sagaContext.Object, | ||
CancellationToken.None); | ||
await Sut.HandleAsync( | ||
A<DomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent>>(), | ||
_sagaContext.Object, | ||
CancellationToken.None); | ||
var exception = (Exception)null; | ||
|
||
// Act | ||
try | ||
{ | ||
await Sut.PublishAsync( | ||
_commandBus.Object, | ||
CancellationToken.None); | ||
} | ||
catch (Exception e) | ||
{ | ||
exception = e; | ||
} | ||
|
||
// Assert | ||
exception.Should().NotBeNull(); | ||
exception.Should().BeAssignableTo<SagaPublishException>(); | ||
var sagaPublishException = exception as SagaPublishException; | ||
sagaPublishException.InnerExceptions.Count.Should().Be(2); | ||
foreach (var innerException in sagaPublishException.InnerExceptions) | ||
{ | ||
innerException.Should().BeAssignableTo<CommandException>(); | ||
var commandException = innerException as CommandException; | ||
commandException.Message.Should().Contain(message); | ||
commandException.Message.Should().Contain(Sut.Id.ToString()); | ||
commandException.CommandType.Should().Be(typeof(ThingyAddMessageCommand)); | ||
commandException.ExecutionResult.Should().NotBeNull(); | ||
commandException.ExecutionResult.IsSuccess.Should().BeFalse(); | ||
commandException.ExecutionResult.ToString().Should().Contain(message); | ||
} | ||
} | ||
|
||
[Test] | ||
public async Task AggregateSaga_PublishAsync_ExceptionIsWrapped() | ||
{ | ||
// Arrange | ||
var message = Guid.NewGuid().ToString(); | ||
_commandBus.Setup( | ||
a => a.PublishAsync( | ||
It.IsAny<ICommand<ThingyAggregate, ThingyId, IExecutionResult>>(), | ||
It.IsAny<CancellationToken>())) | ||
.Callback(() => throw new ApplicationException(message)); | ||
await Sut.HandleAsync( | ||
A<DomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent>>(), | ||
_sagaContext.Object, | ||
CancellationToken.None); | ||
var exception = (Exception)null; | ||
|
||
// Act | ||
try | ||
{ | ||
await Sut.PublishAsync( | ||
_commandBus.Object, | ||
CancellationToken.None); | ||
} | ||
catch (Exception e) | ||
{ | ||
exception = e; | ||
} | ||
|
||
// Assert | ||
exception.Should().NotBeNull(); | ||
exception.Should().BeAssignableTo<SagaPublishException>(); | ||
var sagaPublishException = exception as SagaPublishException; | ||
sagaPublishException.InnerExceptions.Count.Should().Be(1); | ||
var innerException = sagaPublishException.InnerExceptions[0]; | ||
innerException.Should().BeAssignableTo<CommandException>(); | ||
var commandException = innerException as CommandException; | ||
commandException.Message.Should().Contain(message); | ||
commandException.Message.Should().Contain(Sut.Id.ToString()); | ||
commandException.CommandType.Should().Be(typeof(ThingyAddMessageCommand)); | ||
commandException.InnerException.Should().NotBeNull(); | ||
commandException.InnerException.Should().BeAssignableTo<ApplicationException>(); | ||
commandException.InnerException.Message.Should().Be(message); | ||
} | ||
|
||
[Test] | ||
public async Task AggregateSaga_PublishAsync_TwoExceptionsAreWrapped() | ||
{ | ||
// Arrange | ||
var message = Guid.NewGuid().ToString(); | ||
_commandBus.Setup( | ||
a => a.PublishAsync( | ||
It.IsAny<ICommand<ThingyAggregate, ThingyId, IExecutionResult>>(), | ||
It.IsAny<CancellationToken>())) | ||
.Callback(() => throw new ApplicationException(message)); | ||
await Sut.HandleAsync( | ||
A<DomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent>>(), | ||
_sagaContext.Object, | ||
CancellationToken.None); | ||
await Sut.HandleAsync( | ||
A<DomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent>>(), | ||
_sagaContext.Object, | ||
CancellationToken.None); | ||
var exception = (Exception)null; | ||
|
||
// Act | ||
try | ||
{ | ||
await Sut.PublishAsync( | ||
_commandBus.Object, | ||
CancellationToken.None); | ||
} | ||
catch (Exception e) | ||
{ | ||
exception = e; | ||
} | ||
|
||
// Assert | ||
exception.Should().NotBeNull(); | ||
exception.Should().BeAssignableTo<SagaPublishException>(); | ||
var sagaPublishException = exception as SagaPublishException; | ||
sagaPublishException.InnerExceptions.Count.Should().Be(2); | ||
foreach (var innerException in sagaPublishException.InnerExceptions) | ||
{ | ||
innerException.Should().BeAssignableTo<CommandException>(); | ||
var commandException = innerException as CommandException; | ||
commandException.Message.Should().Contain(message); | ||
commandException.Message.Should().Contain(Sut.Id.ToString()); | ||
commandException.CommandType.Should().Be(typeof(ThingyAddMessageCommand)); | ||
commandException.InnerException.Should().NotBeNull(); | ||
commandException.InnerException.Should().BeAssignableTo<ApplicationException>(); | ||
commandException.InnerException.Message.Should().Be(message); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.