BaseRepository takes an ILogger via its constructor and logs the failing file path and exception in Save's catch block before rethrowing. Every concrete repository takes ILogger<ThisRepo> and passes it up so failures are categorised by repository type. Pulls Microsoft.Extensions.Logging.Abstractions into the Db project. TransactionRepositoryTestShould and AccountRepositoryTestShould pass NullLogger<T>.Instance. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
113 lines
3.8 KiB
C#
113 lines
3.8 KiB
C#
using Microsoft.Extensions.Logging.Abstractions;
|
|
using NSubstitute;
|
|
using Schaad.Accounting.Interfaces;
|
|
using Schaad.Accounting.Models;
|
|
using Schaad.Accounting.Repositories;
|
|
using Shouldly;
|
|
|
|
namespace Schaad.Accounting.Tests;
|
|
|
|
public class AccountRepositoryTestShould : IDisposable
|
|
{
|
|
private readonly string dbDir;
|
|
private readonly ISettingsService settingsService;
|
|
private readonly AccountRepository sut;
|
|
|
|
public AccountRepositoryTestShould()
|
|
{
|
|
dbDir = Path.Combine(Path.GetTempPath(), "AccountingNext-tests-" + Guid.NewGuid().ToString("N"));
|
|
Directory.CreateDirectory(dbDir);
|
|
|
|
settingsService = Substitute.For<ISettingsService>();
|
|
settingsService.GetDbPath().Returns(dbDir);
|
|
settingsService.GetLastYearDbPath().Returns(Path.Combine(dbDir, "no-such-dir"));
|
|
|
|
sut = new AccountRepository(settingsService, new RepositoryCache(), NullLogger<AccountRepository>.Instance);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Directory.Exists(dbDir))
|
|
{
|
|
Directory.Delete(dbDir, recursive: true);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void AssignNewIdWhenSavingAccountWithoutId()
|
|
{
|
|
var account = new Account { Number = 1000, Name = "Cash", Currency = "CHF" };
|
|
|
|
sut.SaveAccount(account);
|
|
|
|
var stored = sut.GetAccountList().Single();
|
|
stored.Id.ShouldNotBeNullOrEmpty();
|
|
stored.Name.ShouldBe("Cash");
|
|
}
|
|
|
|
[Fact]
|
|
public void UpdateInPlaceWhenSavingAccountWithExistingId()
|
|
{
|
|
sut.SaveAccount(new Account { Number = 1000, Name = "Cash", Currency = "CHF" });
|
|
var id = sut.GetAccountList().Single().Id;
|
|
|
|
sut.SaveAccount(new Account { Id = id, Number = 1000, Name = "Cash renamed", Currency = "CHF" });
|
|
|
|
var accounts = sut.GetAccountList();
|
|
accounts.Count.ShouldBe(1);
|
|
accounts[0].Name.ShouldBe("Cash renamed");
|
|
}
|
|
|
|
[Fact]
|
|
public void DefaultCurrencyToChfWhenSavingAccountWithoutCurrency()
|
|
{
|
|
sut.SaveAccount(new Account { Number = 1000, Name = "Cash", Currency = null! });
|
|
|
|
sut.GetAccountList().Single().Currency.ShouldBe("CHF");
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveAccountWhenDeletingById()
|
|
{
|
|
sut.SaveAccount(new Account { Number = 1000, Name = "Cash", Currency = "CHF" });
|
|
var id = sut.GetAccountList().Single().Id;
|
|
|
|
sut.DeleteAccount(id);
|
|
|
|
sut.GetAccountList().ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void ReturnAccountWhenLookingUpByBankAccountNumber()
|
|
{
|
|
sut.SaveAccount(new Account { Number = 1010, Name = "Checking", Currency = "CHF", BankAccountNumber = "CH01" });
|
|
sut.SaveAccount(new Account { Number = 1020, Name = "Savings", Currency = "CHF", BankAccountNumber = "CH02" });
|
|
|
|
sut.GetAccountForBankAccountNumber("CH01").Name.ShouldBe("Checking");
|
|
sut.GetAccountForBankAccountNumber("CH02").Name.ShouldBe("Savings");
|
|
sut.GetAccountForBankAccountNumber("CH99").ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void UpdateLastBankBalanceWhenSavingBankBalance()
|
|
{
|
|
sut.SaveAccount(new Account { Number = 1010, Name = "Checking", Currency = "CHF", BankAccountNumber = "CH01" });
|
|
|
|
sut.SaveBankAccountBalance("CH01", 1234.56m);
|
|
|
|
sut.GetAccountForBankAccountNumber("CH01").LastBankBalance.ShouldBe(1234.56m);
|
|
}
|
|
|
|
[Fact]
|
|
public void SurviveConstructorReRunWhenAccountsFileAlreadyExists()
|
|
{
|
|
sut.SaveAccount(new Account { Number = 1000, Name = "Cash", Currency = "CHF" });
|
|
|
|
// Re-construct with the same directory: existing file, no year rollover, no data loss.
|
|
var fresh = new AccountRepository(settingsService, new RepositoryCache(), NullLogger<AccountRepository>.Instance);
|
|
|
|
var accounts = fresh.GetAccountList();
|
|
accounts.Count.ShouldBe(1);
|
|
accounts[0].Name.ShouldBe("Cash");
|
|
}
|
|
}
|