Skip to content

Commit

Permalink
Merge pull request #689 from SkillsFundingAgency/CV-657-CommandHandle…
Browse files Browse the repository at this point in the history
…r-to-be-idempotent

Cv 657 command handler to be idempotent
  • Loading branch information
Najamuddin-Muhammad authored Mar 10, 2020
2 parents e8ed5be + a42ae19 commit 801b021
Show file tree
Hide file tree
Showing 20 changed files with 300 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using SFA.DAS.CommitmentsV2.Messages.Commands;
using SFA.DAS.CommitmentsV2.Messages.Events;
using SFA.DAS.CommitmentsV2.Models;
using SFA.DAS.CommitmentsV2.TestHelpers;
using SFA.DAS.CommitmentsV2.Types;
using SFA.DAS.UnitOfWork.Context;

Expand Down Expand Up @@ -44,6 +45,18 @@ public void Handle_WhenHandlingTransferSenderApproveCohortCommand_ThenItShouldPu
fixture.VerifyTransferRequestApprovedEventIsPublished();
}

[Test]
public void Handle_WhenHandlingTransferSenderApproveCohortCommand_ForASecondTime_ThenItShouldLogWarningAndReturn()
{
var fixture = new ApproveTransferRequestCommandHandlerTestsFixture();
fixture.SetupTransfer().SetupTransferSenderApproveCohortCommand().SetTransferStatusToApproved();

fixture.Handle();

fixture.VerifyTransferRequestApprovedEventIsNotPublished();
fixture.VerifyHasWarning();
}

[Test]
public void Handle_WhenHandlingTransferSenderApproveCohortCommand_ThenItShouldPublishChangeTrackingEvents()
{
Expand Down Expand Up @@ -136,6 +149,12 @@ public ApproveTransferRequestCommandHandlerTestsFixture SetupTransfer()
return this;
}

public ApproveTransferRequestCommandHandlerTestsFixture SetTransferStatusToApproved()
{
TransferRequest.Status = TransferApprovalStatus.Approved;
return this;
}

public Task Handle()
{
return Sut.Handle(TransferSenderApproveCohortCommand, Mock.Of<IMessageHandlerContext>());
Expand All @@ -154,6 +173,11 @@ public void VerifyHasError()
Assert.IsTrue(Logger.HasErrors);
}

public void VerifyHasWarning()
{
Assert.IsTrue(Logger.HasWarnings);
}

public void VerifyTransferRequestApprovedEventIsPublished()
{
var list = UnitOfWorkContext.GetEvents().OfType<TransferRequestApprovedEvent>().ToList();
Expand All @@ -165,6 +189,13 @@ public void VerifyTransferRequestApprovedEventIsPublished()
Assert.AreEqual(Now, list[0].ApprovedOn);
}

public void VerifyTransferRequestApprovedEventIsNotPublished()
{
var list = UnitOfWorkContext.GetEvents().OfType<TransferRequestApprovedEvent>().ToList();

Assert.AreEqual(0, list.Count);
}

public void VerifyEntityIsBeingTracked()
{
var list = UnitOfWorkContext.GetEvents().OfType<EntityStateChangedEvent>().Where(x=>x.StateChangeType == UserAction.ApproveTransferRequest).ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
using System.Threading.Tasks;
using AutoFixture;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NUnit.Framework;
using Moq;
using NServiceBus;
using SFA.DAS.CommitmentsV2.Data;
using SFA.DAS.CommitmentsV2.MessageHandlers.CommandHandlers;
using SFA.DAS.CommitmentsV2.Messages.Commands;
using SFA.DAS.CommitmentsV2.Models;
using SFA.DAS.CommitmentsV2.TestHelpers;
using SFA.DAS.CommitmentsV2.Types;

namespace SFA.DAS.CommitmentsV2.MessageHandlers.UnitTests.CommandHandlers
Expand All @@ -26,27 +26,44 @@ public void Arrange()
}

[Test]
public async Task When_HandlingCommand_Approve_Cohort()
public async Task When_HandlingCommand_ApproveCohort()
{
await _fixture.Handle();
_fixture.VerifyCohortApproval();
}

[Test]
public async Task When_HandlingCommand_ApproveCohort_Again_ShouldNotCallCohortApprovalAndShouldLogWarning()
{
await _fixture.AddAlreadyApprovedByProvider().Handle();
_fixture.VerifyCohortApprovalWasNotCalled();
_fixture.VerifyHasWarning();
}

[Test]
public void Handle_WhenHandlingCommandAndItFails_ThenItShouldThrowAnExceptionAndLogIt()
{
Assert.ThrowsAsync<NullReferenceException>( () =>_fixture.SetupNullMessage().Handle());
_fixture.VerifyHasError();
}

public class ProviderApproveCohortCommandHandlerTestsFixture
{
private ProviderApproveCohortCommandHandler _handler;
private ProviderApproveCohortCommand _command;
public Mock<ProviderCommitmentsDbContext> _dbContext { get; set; }
private Mock<IMessageHandlerContext> _messageHandlerContext;
private FakeLogger<ProviderApproveCohortCommandHandler> _logger;
private Mock<Cohort> _cohort;

public ProviderApproveCohortCommandHandlerTestsFixture()
{
var autoFixture = new Fixture();

_dbContext = new Mock<ProviderCommitmentsDbContext>(new DbContextOptionsBuilder<ProviderCommitmentsDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options) { CallBase = true };

_handler = new ProviderApproveCohortCommandHandler(Mock.Of<ILogger<ProviderApproveCohortCommandHandler>>(),
_logger = new FakeLogger<ProviderApproveCohortCommandHandler>();

_handler = new ProviderApproveCohortCommandHandler(_logger,
new Lazy<ProviderCommitmentsDbContext>(() => _dbContext.Object));

_messageHandlerContext = new Mock<IMessageHandlerContext>();
Expand All @@ -55,14 +72,28 @@ public ProviderApproveCohortCommandHandlerTestsFixture()

_cohort = new Mock<Cohort>();
_cohort.Setup(x => x.Id).Returns(_command.CohortId);
_cohort.Setup(x => x.Approvals).Returns(Party.None);
_cohort.Setup(x => x.IsApprovedByAllParties).Returns(false);

_cohort.Setup(x =>
x.Approve(Party.Provider, It.IsAny<string>(), It.IsAny<UserInfo>(), It.IsAny<DateTime>()));

_dbContext.Object.Cohorts.Add(_cohort.Object);
_dbContext.Object.SaveChanges();
}

public ProviderApproveCohortCommandHandlerTestsFixture AddAlreadyApprovedByProvider()
{
_cohort.Setup(x => x.Approvals).Returns(Party.Provider);
return this;
}

public ProviderApproveCohortCommandHandlerTestsFixture SetupNullMessage()
{
_command = null;
return this;
}

public async Task Handle()
{
await _handler.Handle(_command, _messageHandlerContext.Object);
Expand All @@ -72,6 +103,21 @@ public void VerifyCohortApproval()
{
_cohort.Verify(x=> x.Approve(Party.Provider, It.IsAny<string>(), It.IsAny<UserInfo>(), It.IsAny<DateTime>()), Times.Once);
}

public void VerifyCohortApprovalWasNotCalled()
{
_cohort.Verify(x => x.Approve(It.IsAny<Party>(), It.IsAny<string>(), It.IsAny<UserInfo>(), It.IsAny<DateTime>()), Times.Never);
}

public void VerifyHasError()
{
Assert.IsTrue(_logger.HasErrors);
}

public void VerifyHasWarning()
{
Assert.IsTrue(_logger.HasWarnings);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
using System.Threading.Tasks;
using AutoFixture;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NUnit.Framework;
using Moq;
using NServiceBus;
using SFA.DAS.CommitmentsV2.Data;
using SFA.DAS.CommitmentsV2.MessageHandlers.CommandHandlers;
using SFA.DAS.CommitmentsV2.Messages.Commands;
using SFA.DAS.CommitmentsV2.Models;
using SFA.DAS.CommitmentsV2.TestHelpers;
using SFA.DAS.CommitmentsV2.Types;

namespace SFA.DAS.CommitmentsV2.MessageHandlers.UnitTests.CommandHandlers
Expand All @@ -32,21 +32,38 @@ public async Task When_HandlingCommand_CohortIsSentToOtherParty()
_fixture.VerifyCohortIsSentToOtherParty();
}

[Test]
public async Task When_HandlingCommand_CohortIsAlreadySentToOtherParty_Then_ShouldNotCallSendToOtherPartyAndLogWarning()
{
await _fixture.SetWithPartyToEmployer().Handle();
_fixture.VerifySendToOtherPartyIsNotCalled();
_fixture.VerifyHasWarning();
}

[Test]
public void Handle_WhenHandlingCommandAndItFails_ThenItShouldThrowAnExceptionAndLogIt()
{
Assert.ThrowsAsync<NullReferenceException>(() => _fixture.SetupNullMessage().Handle());
_fixture.VerifyHasError();
}

public class ProviderSendCohortCommandHandlerTestsFixture
{
private ProviderSendCohortCommandHandler _handler;
private ProviderSendCohortCommand _command;
public Mock<ProviderCommitmentsDbContext> _dbContext { get; set; }
private Mock<IMessageHandlerContext> _messageHandlerContext;
private FakeLogger<ProviderSendCohortCommandHandler> _logger;
private Mock<Cohort> _cohort;

public ProviderSendCohortCommandHandlerTestsFixture()
{
var autoFixture = new Fixture();

_dbContext = new Mock<ProviderCommitmentsDbContext>(new DbContextOptionsBuilder<ProviderCommitmentsDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options) { CallBase = true };
_logger = new FakeLogger<ProviderSendCohortCommandHandler>();

_handler = new ProviderSendCohortCommandHandler(Mock.Of<ILogger<ProviderSendCohortCommandHandler>>(),
_handler = new ProviderSendCohortCommandHandler(_logger,
new Lazy<ProviderCommitmentsDbContext>(() => _dbContext.Object));

_messageHandlerContext = new Mock<IMessageHandlerContext>();
Expand All @@ -55,6 +72,7 @@ public ProviderSendCohortCommandHandlerTestsFixture()

_cohort = new Mock<Cohort>();
_cohort.Setup(x => x.Id).Returns(_command.CohortId);
_cohort.Setup(x => x.WithParty).Returns(Party.Provider);
_cohort.Setup(x => x.IsApprovedByAllParties).Returns(false);
_cohort.Setup(x =>
x.SendToOtherParty(Party.Provider, It.IsAny<string>(), It.IsAny<UserInfo>(), It.IsAny<DateTime>()));
Expand All @@ -63,6 +81,17 @@ public ProviderSendCohortCommandHandlerTestsFixture()
_dbContext.Object.SaveChanges();
}

public ProviderSendCohortCommandHandlerTestsFixture SetWithPartyToEmployer()
{
_cohort.Setup(x => x.WithParty).Returns(Party.Employer);
return this;
}
public ProviderSendCohortCommandHandlerTestsFixture SetupNullMessage()
{
_command = null;
return this;
}

public async Task Handle()
{
await _handler.Handle(_command, _messageHandlerContext.Object);
Expand All @@ -72,6 +101,21 @@ public void VerifyCohortIsSentToOtherParty()
{
_cohort.Verify(x => x.SendToOtherParty(Party.Provider, It.IsAny<string>(), It.IsAny<UserInfo>(), It.IsAny<DateTime>()), Times.Once);
}

public void VerifySendToOtherPartyIsNotCalled()
{
_cohort.Verify(x => x.SendToOtherParty(It.IsAny<Party>(), It.IsAny<string>(), It.IsAny<UserInfo>(), It.IsAny<DateTime>()), Times.Never);
}

public void VerifyHasError()
{
Assert.IsTrue(_logger.HasErrors);
}

public void VerifyHasWarning()
{
Assert.IsTrue(_logger.HasWarnings);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Logging;
using Moq;
using NServiceBus;
using NUnit.Framework;
Expand All @@ -14,6 +13,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using SFA.DAS.CommitmentsV2.TestHelpers;

namespace SFA.DAS.CommitmentsV2.MessageHandlers.UnitTests.CommandHandlers
{
Expand All @@ -29,9 +29,10 @@ public void Setup()
}

[Test]
public Task WhenHandlingRejectTransferRequestCommand_AndDbDoesNotHaveRecord_ThenExceptionThrown()
public void WhenHandlingRejectTransferRequestCommand_AndDbDoesNotHaveRecord_ThenExceptionThrownAndLogged()
{
return Task.FromResult(Assert.ThrowsAsync<InvalidOperationException>(() => _fixture.Act()));
Assert.ThrowsAsync<InvalidOperationException>(() => _fixture.Act());
_fixture.VerifyHasError();
}

[Test]
Expand All @@ -44,7 +45,6 @@ public async Task WhenHandlingRejectTransferRequestCommand_AndDbHasRecord_ThenNo

[TestCase(TransferApprovalStatus.Pending, false)]
[TestCase(TransferApprovalStatus.Approved, true)]
[TestCase(TransferApprovalStatus.Rejected, true)]
public async Task WhenCallingRejectOnTransferRequest_ThenTransferApprovalStatusHandledCorrectly(TransferApprovalStatus status, bool shouldThrowException)
{
_fixture
Expand All @@ -61,6 +61,17 @@ public async Task WhenCallingRejectOnTransferRequest_ThenTransferApprovalStatusH
}
}

[Test]
public async Task WhenCallingRejectOnTransferRequestAndAlreadyBeenRejected_ThenShouldSwallowMessageAndLogWarning()
{
_fixture
.WithTransferRequestAndCohortInDatabase()
.WithTransferApprovalStatus(TransferApprovalStatus.Rejected);

await _fixture.Act();
_fixture.VerifyHasWarning();
}

[Test]
public async Task WhenCallingRejectOnTransferRequest_ThenEntityIsTracked()
{
Expand Down Expand Up @@ -106,7 +117,7 @@ public class RejectTransferRequestCommandHandlerTestsFixture
private TransferRequest _transferRequest;
private Cohort _cohort;
private ProviderCommitmentsDbContext _db;
private Mock<ILogger<RejectTransferRequestCommandHandler>> _mockLogger;
private FakeLogger<RejectTransferRequestCommandHandler> _logger;
private Mock<IMessageHandlerContext> _mockMessageHandlerContext;
private RejectTransferRequestCommandHandler _sut;
private UnitOfWorkContext _unitOfWorkContext;
Expand Down Expand Up @@ -137,12 +148,12 @@ public RejectTransferRequestCommandHandlerTestsFixture()
.ConfigureWarnings(w => w.Throw(RelationalEventId.QueryClientEvaluationWarning))
.Options);

_mockLogger = new Mock<ILogger<RejectTransferRequestCommandHandler>>();
_logger = new FakeLogger<RejectTransferRequestCommandHandler>();
_mockMessageHandlerContext = new Mock<IMessageHandlerContext>();
_rejectedOnDate = new DateTime(2020, 01, 30, 14, 22, 00);
_command = new RejectTransferRequestCommand(_transferRequestId, _rejectedOnDate, _userInfo);
_unitOfWorkContext = new UnitOfWorkContext();
_sut = new RejectTransferRequestCommandHandler(new Lazy<ProviderCommitmentsDbContext>(() => _db), _mockLogger.Object);
_sut = new RejectTransferRequestCommandHandler(new Lazy<ProviderCommitmentsDbContext>(() => _db), _logger);
}

public async Task Act() => await _sut.Handle(_command, _mockMessageHandlerContext.Object);
Expand Down Expand Up @@ -201,5 +212,15 @@ public void VerifyEntityIsBeingTracked()
Assert.AreEqual(_userInfo.UserDisplayName, rejectedEvent.UpdatingUserName);
Assert.AreEqual(Party.TransferSender, rejectedEvent.UpdatingParty);
}

public void VerifyHasError()
{
Assert.IsTrue(_logger.HasErrors);
}

public void VerifyHasWarning()
{
Assert.IsTrue(_logger.HasWarnings);
}
}
}
Loading

0 comments on commit 801b021

Please sign in to comment.