Skip to content

Commit

Permalink
Added unit tests for GroupCheckoutSaga
Browse files Browse the repository at this point in the history
  • Loading branch information
oskardudycz committed Dec 3, 2022
1 parent 53edb0a commit 1d1d79d
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using Core.Commands;
using FluentAssertions;
using HotelManagement.GroupCheckouts;
using HotelManagement.GuestStayAccounts;
using Xunit;
using GuestCheckoutFailed = HotelManagement.GuestStayAccounts.GuestCheckoutFailed;

namespace HotelManagement.Tests.GroupCheckouts;

using static GuestCheckoutFailed;

public class GroupCheckoutSagaTests
{
private readonly GroupCheckoutSaga saga;
private readonly AsyncCommandBusStub commandBus = new();
private readonly Guid groupCheckoutId = Guid.NewGuid();
private readonly Guid clerkId = Guid.NewGuid();
private readonly DateTimeOffset now = DateTimeOffset.UtcNow;
private readonly CancellationToken ct = CancellationToken.None;

public GroupCheckoutSagaTests() =>
saga = new GroupCheckoutSaga(commandBus);

[Fact]
public async Task GroupCheckoutInitiated_ShouldSchedule_CheckOutGuestForEachGuesAndRecordGuestCheckoutsInitiation()
{
// Given
var guestStayAccountIds = new[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
var @event = new GroupCheckoutInitiated(groupCheckoutId, clerkId, guestStayAccountIds, now);

// When
await saga.Handle(@event, ct);

// Then
commandBus.ShouldHaveScheduled(
new CheckOutGuest(guestStayAccountIds[0], groupCheckoutId),
new CheckOutGuest(guestStayAccountIds[1], groupCheckoutId),
new CheckOutGuest(guestStayAccountIds[2], groupCheckoutId),
new RecordGuestCheckoutsInitiation(groupCheckoutId, guestStayAccountIds)
);
}

[Fact]
public async Task GuestCheckedOutWithGroupCheckOutId_ShouldSchedule_RecordGuestCheckoutCompletion()
{
// Given
var guestStayAccountId = Guid.NewGuid();
var @event = new GuestCheckedOut(guestStayAccountId, now, groupCheckoutId);

// When
await saga.Handle(@event, ct);

// Then
commandBus.ShouldHaveScheduled(
new RecordGuestCheckoutCompletion(groupCheckoutId, guestStayAccountId, now)
);
}

[Fact]
public async Task GuestCheckedOutWithoutGroupCheckOutId_ShouldNotSchedule_RecordsGuestCheckoutCompletion()
{
// Given
var guestStayAccountId = Guid.NewGuid();
var @event = new GuestCheckedOut(guestStayAccountId, now);

// When
await saga.Handle(@event, ct);

// Then
commandBus.ShouldNotHaveScheduledCommands(
new RecordGuestCheckoutCompletion(groupCheckoutId, guestStayAccountId, now)
);
}

[Fact]
public async Task GuestCheckoutFailedWithGroupCheckOutId_ShouldSchedule_RecordGuestCheckoutFailure()
{
// Given
var guestStayAccountId = Guid.NewGuid();
var @event = new GuestCheckoutFailed(guestStayAccountId, FailureReason.BalanceNotSettled, now, groupCheckoutId);

// When
await saga.Handle(@event, ct);

// Then
commandBus.ShouldHaveScheduled(
new RecordGuestCheckoutFailure(groupCheckoutId, guestStayAccountId, now)
);
}

[Fact]
public async Task GuestCheckoutFailedWithoutGroupCheckOutId_ShouldNotSchedule_RecordGuestCheckoutFailure()
{
// Given
var guestStayAccountId = Guid.NewGuid();
var @event = new GuestCheckoutFailed(guestStayAccountId, FailureReason.BalanceNotSettled, now);

// When
await saga.Handle(@event, ct);

// Then
commandBus.ShouldNotHaveScheduledCommands(
new RecordGuestCheckoutFailure(groupCheckoutId, guestStayAccountId, now)
);
}
}

internal class AsyncCommandBusStub: IAsyncCommandBus
{
private readonly List<object> commands = new();

public Task Schedule<TCommand>(TCommand command, CancellationToken ct = default) where TCommand : notnull
{
commands.Add(command);

return Task.CompletedTask;
}

public void ShouldNotHaveScheduledCommands(params object[] expected)
{
commands.Should().NotContain(expected);
}

public void ShouldHaveScheduled(params object[] expected)
{
commands.Should().Contain(expected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ namespace HotelManagement.GroupCheckouts;

public class GroupCheckoutSaga
{
private readonly ICommandBus commandBus;
private readonly IAsyncCommandBus commandBus;

public GroupCheckoutSaga(ICommandBus commandBus) =>
public GroupCheckoutSaga(IAsyncCommandBus commandBus) =>
this.commandBus = commandBus;

public async Task Handle(GroupCheckoutInitiated @event, CancellationToken ct)
{
foreach (var guestAccountId in @event.GuestStayIds)
{
await commandBus.Send(
await commandBus.Schedule(
new CheckOutGuest(guestAccountId, @event.GroupCheckoutId),
ct
);
}

await commandBus.Send(
await commandBus.Schedule(
new RecordGuestCheckoutsInitiation(
@event.GroupCheckoutId,
@event.GuestStayIds
Expand All @@ -34,7 +34,7 @@ public Task Handle(GuestStayAccounts.GuestCheckedOut @event, CancellationToken c
if (!@event.GroupCheckOutId.HasValue)
return Task.CompletedTask;

return commandBus.Send(
return commandBus.Schedule(
new RecordGuestCheckoutCompletion(
@event.GroupCheckOutId.Value,
@event.GuestStayId,
Expand All @@ -49,7 +49,7 @@ public Task Handle(GuestStayAccounts.GuestCheckoutFailed @event, CancellationTok
if (!@event.GroupCheckOutId.HasValue)
return Task.CompletedTask;

return commandBus.Send(
return commandBus.Schedule(
new RecordGuestCheckoutFailure(
@event.GroupCheckOutId.Value,
@event.GuestStayId,
Expand Down

0 comments on commit 1d1d79d

Please sign in to comment.