From 398867a839662bc1345fccc30bdd832417175406 Mon Sep 17 00:00:00 2001 From: Mike Hanson <8196328+themikecom@users.noreply.github.com> Date: Thu, 18 Jun 2020 10:13:22 -0700 Subject: [PATCH 1/2] Parameterize AmazonSQSClient to allow testing --- .../Implementations/AmazonSqsBlockIpService.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Core/Services/Implementations/AmazonSqsBlockIpService.cs b/src/Core/Services/Implementations/AmazonSqsBlockIpService.cs index 7090a753b..6a6fe6dfd 100644 --- a/src/Core/Services/Implementations/AmazonSqsBlockIpService.cs +++ b/src/Core/Services/Implementations/AmazonSqsBlockIpService.cs @@ -7,7 +7,7 @@ namespace Bit.Core.Services { public class AmazonSqsBlockIpService : IBlockIpService, IDisposable { - private readonly AmazonSQSClient _client; + private readonly IAmazonSQS _client; private string _blockIpQueueUrl; private string _unblockIpQueueUrl; private bool _didInit = false; @@ -15,6 +15,17 @@ namespace Bit.Core.Services public AmazonSqsBlockIpService( GlobalSettings globalSettings) + : this(globalSettings, new AmazonSQSClient( + globalSettings.Amazon.AccessKeyId, + globalSettings.Amazon.AccessKeySecret, + RegionEndpoint.GetBySystemName(globalSettings.Amazon.Region)) + ) + { + } + + public AmazonSqsBlockIpService( + GlobalSettings globalSettings, + IAmazonSQS amazonSqs) { if (string.IsNullOrWhiteSpace(globalSettings.Amazon?.AccessKeyId)) { @@ -28,8 +39,8 @@ namespace Bit.Core.Services { throw new ArgumentNullException(nameof(globalSettings.Amazon.Region)); } - _client = new AmazonSQSClient(globalSettings.Amazon.AccessKeyId, - globalSettings.Amazon.AccessKeySecret, RegionEndpoint.GetBySystemName(globalSettings.Amazon.Region)); + + _client = amazonSqs; } public void Dispose() From 4115b2e13eb3fe412677e89fcce7e9e8920eb6a7 Mon Sep 17 00:00:00 2001 From: Mike Hanson <8196328+themikecom@users.noreply.github.com> Date: Thu, 18 Jun 2020 10:16:04 -0700 Subject: [PATCH 2/2] Add unit test coverage for AmazonSqsBlockIpService --- .../Services/AmazonSqsBlockIpServiceTests.cs | 58 ++++++++++++++++--- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/test/Core.Test/Services/AmazonSqsBlockIpServiceTests.cs b/test/Core.Test/Services/AmazonSqsBlockIpServiceTests.cs index abc9c9743..875a31f7c 100644 --- a/test/Core.Test/Services/AmazonSqsBlockIpServiceTests.cs +++ b/test/Core.Test/Services/AmazonSqsBlockIpServiceTests.cs @@ -1,4 +1,6 @@ using System; +using System.Threading.Tasks; +using Amazon.SQS; using Bit.Core.Services; using NSubstitute; using Xunit; @@ -10,12 +12,23 @@ namespace Bit.Core.Test.Services private readonly AmazonSqsBlockIpService _sut; private readonly GlobalSettings _globalSettings; + private readonly IAmazonSQS _amazonSqs; public AmazonSqsBlockIpServiceTests() { - _globalSettings = new GlobalSettings(); + _globalSettings = new GlobalSettings + { + Amazon = + { + AccessKeyId = "AccessKeyId-AmazonSesMailDeliveryServiceTests", + AccessKeySecret = "AccessKeySecret-AmazonSesMailDeliveryServiceTests", + Region = "Region-AmazonSesMailDeliveryServiceTests" + } + }; - _sut = new AmazonSqsBlockIpService(_globalSettings); + _amazonSqs = Substitute.For(); + + _sut = new AmazonSqsBlockIpService(_globalSettings, _amazonSqs); } public void Dispose() @@ -23,12 +36,43 @@ namespace Bit.Core.Test.Services _sut?.Dispose(); } - // Remove this test when we add actual tests. It only proves that - // we've properly constructed the system under test. - [Fact(Skip = "Needs additional work")] - public void ServiceExists() + [Fact] + public async Task BlockIpAsync_UnblockCalled_WhenNotPermanent() { - Assert.NotNull(_sut); + const string expectedIp = "ip"; + + await _sut.BlockIpAsync(expectedIp, false); + + await _amazonSqs.Received(2).SendMessageAsync( + Arg.Any(), + Arg.Is(expectedIp)); + } + + [Fact] + public async Task BlockIpAsync_UnblockNotCalled_WhenPermanent() + { + const string expectedIp = "ip"; + + await _sut.BlockIpAsync(expectedIp, true); + + await _amazonSqs.Received(1).SendMessageAsync( + Arg.Any(), + Arg.Is(expectedIp)); + } + + [Fact] + public async Task BlockIpAsync_NotBlocked_WhenAlreadyBlockedRecently() + { + const string expectedIp = "ip"; + + await _sut.BlockIpAsync(expectedIp, true); + + // The second call should hit the already blocked guard clause + await _sut.BlockIpAsync(expectedIp, true); + + await _amazonSqs.Received(1).SendMessageAsync( + Arg.Any(), + Arg.Is(expectedIp)); } } }