diff --git a/src/Core/Services/Implementations/AmazonSqsBlockIpService.cs b/src/Core/Services/Implementations/AmazonSqsBlockIpService.cs
index 7090a753ba..6a6fe6dfda 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()
diff --git a/test/Core.Test/Services/AmazonSqsBlockIpServiceTests.cs b/test/Core.Test/Services/AmazonSqsBlockIpServiceTests.cs
index abc9c97437..875a31f7c9 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<IAmazonSQS>();
+
+            _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<string>(),
+                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<string>(),
+                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<string>(),
+                Arg.Is(expectedIp));
         }
     }
 }