diff --git a/ClearBank.DeveloperTest.Tests/ClearBank.DeveloperTest.Tests.csproj b/ClearBank.DeveloperTest.Tests/ClearBank.DeveloperTest.Tests.csproj
index b21ab73..bc0ae4b 100644
--- a/ClearBank.DeveloperTest.Tests/ClearBank.DeveloperTest.Tests.csproj
+++ b/ClearBank.DeveloperTest.Tests/ClearBank.DeveloperTest.Tests.csproj
@@ -3,10 +3,16 @@
net8.0
true
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/ClearBank.DeveloperTest.Tests/Tests/PaymentServiceTests.cs b/ClearBank.DeveloperTest.Tests/Tests/PaymentServiceTests.cs
new file mode 100644
index 0000000..cbd9524
--- /dev/null
+++ b/ClearBank.DeveloperTest.Tests/Tests/PaymentServiceTests.cs
@@ -0,0 +1,73 @@
+using ClearBank.DeveloperTest.Data;
+using ClearBank.DeveloperTest.Services;
+using ClearBank.DeveloperTest.Types;
+using System;
+using Xunit;
+
+namespace ClearBank.DeveloperTest.Tests
+{
+ public class PaymentServiceTests
+ {
+ private class FakeStore : IAccountDataStore
+ {
+ public Account Account { get; set; }
+
+ public Account GetAccount(string accountNumber) => Account;
+
+ public void UpdateAccount(Account account) => Account = account;
+ }
+
+ private class FakeFactory : IAccountDataStoreFactory
+ {
+ public FakeStore Store { get; } = new FakeStore();
+
+ public IAccountDataStore Create(string type) => Store;
+ }
+
+ [Fact]
+ public void Bacs_Fails_When_Account_Null()
+ {
+ var factory = new FakeFactory();
+ factory.Store.Account = null;
+
+ var svc = new PaymentService(factory);
+
+ var req = new MakePaymentRequest { DebtorAccountNumber = "123", Amount = 10m, PaymentScheme = PaymentScheme.Bacs };
+
+ var result = svc.MakePayment(req);
+
+ Assert.False(result.Success);
+ }
+
+ [Fact]
+ public void FasterPayments_Fails_When_Insufficient_Balance()
+ {
+ var factory = new FakeFactory();
+ factory.Store.Account = new Account { AccountNumber = "123", Balance = 5m, AllowedPaymentSchemes = AllowedPaymentSchemes.FasterPayments };
+
+ var svc = new PaymentService(factory);
+
+ var req = new MakePaymentRequest { DebtorAccountNumber = "123", Amount = 10m, PaymentScheme = PaymentScheme.FasterPayments };
+
+ var result = svc.MakePayment(req);
+
+ Assert.False(result.Success);
+ }
+
+ [Fact]
+ public void Chaps_Succeeds_When_Live_And_Allowed()
+ {
+ var factory = new FakeFactory();
+ factory.Store.Account = new Account { AccountNumber = "123", Balance = 100m, AllowedPaymentSchemes = AllowedPaymentSchemes.Chaps, Status = AccountStatus.Live };
+
+ var svc = new PaymentService(factory);
+
+ var req = new MakePaymentRequest { DebtorAccountNumber = "123", Amount = 10m, PaymentScheme = PaymentScheme.Chaps };
+
+ var result = svc.MakePayment(req);
+
+ Assert.True(result.Success);
+ Assert.Equal(90m, factory.Store.Account.Balance);
+ }
+ }
+}
diff --git a/ClearBank.DeveloperTest/Data/AccountDataStore.cs b/ClearBank.DeveloperTest/Data/AccountDataStore.cs
index 89e49dd..a2b8360 100644
--- a/ClearBank.DeveloperTest/Data/AccountDataStore.cs
+++ b/ClearBank.DeveloperTest/Data/AccountDataStore.cs
@@ -2,7 +2,7 @@
namespace ClearBank.DeveloperTest.Data
{
- public class AccountDataStore
+ public class AccountDataStore : IAccountDataStore
{
public Account GetAccount(string accountNumber)
{
diff --git a/ClearBank.DeveloperTest/Data/AccountDataStoreFactory.cs b/ClearBank.DeveloperTest/Data/AccountDataStoreFactory.cs
new file mode 100644
index 0000000..4c95b7c
--- /dev/null
+++ b/ClearBank.DeveloperTest/Data/AccountDataStoreFactory.cs
@@ -0,0 +1,17 @@
+using System.Configuration;
+
+namespace ClearBank.DeveloperTest.Data
+{
+ public class AccountDataStoreFactory : IAccountDataStoreFactory
+ {
+ public IAccountDataStore Create(string type)
+ {
+ if (type == "Backup")
+ {
+ return new BackupAccountDataStore();
+ }
+
+ return new AccountDataStore();
+ }
+ }
+}
diff --git a/ClearBank.DeveloperTest/Data/BackupAccountDataStore.cs b/ClearBank.DeveloperTest/Data/BackupAccountDataStore.cs
index 170362c..d00fbaa 100644
--- a/ClearBank.DeveloperTest/Data/BackupAccountDataStore.cs
+++ b/ClearBank.DeveloperTest/Data/BackupAccountDataStore.cs
@@ -2,7 +2,7 @@
namespace ClearBank.DeveloperTest.Data
{
- public class BackupAccountDataStore
+ public class BackupAccountDataStore : IAccountDataStore
{
public Account GetAccount(string accountNumber)
{
diff --git a/ClearBank.DeveloperTest/Data/IAccountDataStore.cs b/ClearBank.DeveloperTest/Data/IAccountDataStore.cs
new file mode 100644
index 0000000..258ad77
--- /dev/null
+++ b/ClearBank.DeveloperTest/Data/IAccountDataStore.cs
@@ -0,0 +1,10 @@
+using ClearBank.DeveloperTest.Types;
+
+namespace ClearBank.DeveloperTest.Data
+{
+ public interface IAccountDataStore
+ {
+ Account GetAccount(string accountNumber);
+ void UpdateAccount(Account account);
+ }
+}
diff --git a/ClearBank.DeveloperTest/Data/IAccountDataStoreFactory.cs b/ClearBank.DeveloperTest/Data/IAccountDataStoreFactory.cs
new file mode 100644
index 0000000..428497b
--- /dev/null
+++ b/ClearBank.DeveloperTest/Data/IAccountDataStoreFactory.cs
@@ -0,0 +1,7 @@
+namespace ClearBank.DeveloperTest.Data
+{
+ public interface IAccountDataStoreFactory
+ {
+ IAccountDataStore Create(string type);
+ }
+}
diff --git a/ClearBank.DeveloperTest/Services/PaymentService.cs b/ClearBank.DeveloperTest/Services/PaymentService.cs
index 573713d..9aba5b0 100644
--- a/ClearBank.DeveloperTest/Services/PaymentService.cs
+++ b/ClearBank.DeveloperTest/Services/PaymentService.cs
@@ -6,65 +6,44 @@ namespace ClearBank.DeveloperTest.Services
{
public class PaymentService : IPaymentService
{
+ private readonly IAccountDataStoreFactory _factory;
+
+ // Default constructor preserves original behavior
+ public PaymentService() : this(new AccountDataStoreFactory()) { }
+
+ // Allow injection for testability
+ public PaymentService(IAccountDataStoreFactory factory)
+ {
+ _factory = factory;
+ }
+
public MakePaymentResult MakePayment(MakePaymentRequest request)
{
var dataStoreType = ConfigurationManager.AppSettings["DataStoreType"];
- Account account = null;
+ var accountStore = _factory.Create(dataStoreType);
+ var account = accountStore.GetAccount(request.DebtorAccountNumber);
- if (dataStoreType == "Backup")
- {
- var accountDataStore = new BackupAccountDataStore();
- account = accountDataStore.GetAccount(request.DebtorAccountNumber);
- }
- else
- {
- var accountDataStore = new AccountDataStore();
- account = accountDataStore.GetAccount(request.DebtorAccountNumber);
- }
-
- var result = new MakePaymentResult();
+ var result = new MakePaymentResult { Success = true };
- result.Success = true;
-
switch (request.PaymentScheme)
{
case PaymentScheme.Bacs:
- if (account == null)
- {
- result.Success = false;
- }
- else if (!account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.Bacs))
+ if (account == null || !account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.Bacs))
{
result.Success = false;
}
break;
case PaymentScheme.FasterPayments:
- if (account == null)
- {
- result.Success = false;
- }
- else if (!account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.FasterPayments))
- {
- result.Success = false;
- }
- else if (account.Balance < request.Amount)
+ if (account == null || !account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.FasterPayments) || account.Balance < request.Amount)
{
result.Success = false;
}
break;
case PaymentScheme.Chaps:
- if (account == null)
- {
- result.Success = false;
- }
- else if (!account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.Chaps))
- {
- result.Success = false;
- }
- else if (account.Status != AccountStatus.Live)
+ if (account == null || !account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.Chaps) || account.Status != AccountStatus.Live)
{
result.Success = false;
}
@@ -74,17 +53,7 @@ public MakePaymentResult MakePayment(MakePaymentRequest request)
if (result.Success)
{
account.Balance -= request.Amount;
-
- if (dataStoreType == "Backup")
- {
- var accountDataStore = new BackupAccountDataStore();
- accountDataStore.UpdateAccount(account);
- }
- else
- {
- var accountDataStore = new AccountDataStore();
- accountDataStore.UpdateAccount(account);
- }
+ accountStore.UpdateAccount(account);
}
return result;