Add MoneyMap.Tests project with xUnit tests for all new services: - AccountServiceTests: Account retrieval, stats, validation, deletion - CardServiceTests: Card retrieval, stats, validation, deletion - MerchantServiceTests: Merchant CRUD operations - ReferenceDataServiceTests: Reference data retrieval - TransactionServiceTests: Duplicate detection, retrieval, deletion - TransactionStatisticsServiceTests: Statistics calculations - ReceiptMatchingServiceTests: Receipt-to-transaction matching logic - DbContextHelper: In-memory database context factory for test isolation Uses xUnit, Moq, and EF Core InMemory database. Solution file updated to include test project. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
238 lines
6.5 KiB
C#
238 lines
6.5 KiB
C#
using MoneyMap.Models;
|
|
using MoneyMap.Services;
|
|
using MoneyMap.Tests.TestHelpers;
|
|
using Xunit;
|
|
|
|
namespace MoneyMap.Tests.Services;
|
|
|
|
public class AccountServiceTests
|
|
{
|
|
[Fact]
|
|
public async Task GetAllAccountsWithStatsAsync_ReturnsAccountsWithTransactionCounts()
|
|
{
|
|
// Arrange
|
|
using var context = DbContextHelper.CreateInMemoryContext();
|
|
var service = new AccountService(context);
|
|
|
|
var account1 = new Account
|
|
{
|
|
Id = 1,
|
|
Institution = "Bank A",
|
|
AccountType = AccountType.Checking,
|
|
Last4 = "1234",
|
|
Owner = "John Doe"
|
|
};
|
|
var account2 = new Account
|
|
{
|
|
Id = 2,
|
|
Institution = "Bank B",
|
|
AccountType = AccountType.Savings,
|
|
Last4 = "5678",
|
|
Owner = "Jane Smith"
|
|
};
|
|
context.Accounts.AddRange(account1, account2);
|
|
|
|
var transaction1 = new Transaction
|
|
{
|
|
Date = DateTime.Now,
|
|
Amount = -50.00m,
|
|
Name = "Test",
|
|
Memo = "Test",
|
|
AccountId = 1
|
|
};
|
|
var transaction2 = new Transaction
|
|
{
|
|
Date = DateTime.Now,
|
|
Amount = -25.00m,
|
|
Name = "Test",
|
|
Memo = "Test",
|
|
AccountId = 1
|
|
};
|
|
context.Transactions.AddRange(transaction1, transaction2);
|
|
await context.SaveChangesAsync();
|
|
|
|
// Act
|
|
var result = await service.GetAllAccountsWithStatsAsync();
|
|
|
|
// Assert
|
|
Assert.Equal(2, result.Count);
|
|
var account1Stats = result.First(a => a.Id == 1);
|
|
Assert.Equal(2, account1Stats.TransactionCount);
|
|
var account2Stats = result.First(a => a.Id == 2);
|
|
Assert.Equal(0, account2Stats.TransactionCount);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CanDeleteAccountAsync_ReturnsFalse_WhenAccountHasTransactions()
|
|
{
|
|
// Arrange
|
|
using var context = DbContextHelper.CreateInMemoryContext();
|
|
var service = new AccountService(context);
|
|
|
|
var account = new Account
|
|
{
|
|
Id = 1,
|
|
Institution = "Test Bank",
|
|
AccountType = AccountType.Checking,
|
|
Last4 = "1234",
|
|
Owner = "Test Owner"
|
|
};
|
|
context.Accounts.Add(account);
|
|
|
|
var transaction = new Transaction
|
|
{
|
|
Date = DateTime.Now,
|
|
Amount = -50.00m,
|
|
Name = "Test",
|
|
Memo = "Test",
|
|
AccountId = 1
|
|
};
|
|
context.Transactions.Add(transaction);
|
|
await context.SaveChangesAsync();
|
|
|
|
// Act
|
|
var result = await service.CanDeleteAccountAsync(1);
|
|
|
|
// Assert
|
|
Assert.False(result.CanDelete);
|
|
Assert.Contains("transaction", result.Reason, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CanDeleteAccountAsync_ReturnsTrue_WhenAccountHasNoTransactions()
|
|
{
|
|
// Arrange
|
|
using var context = DbContextHelper.CreateInMemoryContext();
|
|
var service = new AccountService(context);
|
|
|
|
var account = new Account
|
|
{
|
|
Id = 1,
|
|
Institution = "Test Bank",
|
|
AccountType = AccountType.Checking,
|
|
Last4 = "1234",
|
|
Owner = "Test Owner"
|
|
};
|
|
context.Accounts.Add(account);
|
|
await context.SaveChangesAsync();
|
|
|
|
// Act
|
|
var result = await service.CanDeleteAccountAsync(1);
|
|
|
|
// Assert
|
|
Assert.True(result.CanDelete);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DeleteAccountAsync_SuccessfullyDeletesAccount_WhenNoTransactions()
|
|
{
|
|
// Arrange
|
|
using var context = DbContextHelper.CreateInMemoryContext();
|
|
var service = new AccountService(context);
|
|
|
|
var account = new Account
|
|
{
|
|
Id = 1,
|
|
Institution = "Test Bank",
|
|
AccountType = AccountType.Checking,
|
|
Last4 = "1234",
|
|
Owner = "Test Owner"
|
|
};
|
|
context.Accounts.Add(account);
|
|
await context.SaveChangesAsync();
|
|
|
|
// Act
|
|
var result = await service.DeleteAccountAsync(1);
|
|
|
|
// Assert
|
|
Assert.True(result.Success);
|
|
Assert.Empty(context.Accounts);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DeleteAccountAsync_FailsToDelete_WhenAccountHasTransactions()
|
|
{
|
|
// Arrange
|
|
using var context = DbContextHelper.CreateInMemoryContext();
|
|
var service = new AccountService(context);
|
|
|
|
var account = new Account
|
|
{
|
|
Id = 1,
|
|
Institution = "Test Bank",
|
|
AccountType = AccountType.Checking,
|
|
Last4 = "1234",
|
|
Owner = "Test Owner"
|
|
};
|
|
context.Accounts.Add(account);
|
|
|
|
var transaction = new Transaction
|
|
{
|
|
Date = DateTime.Now,
|
|
Amount = -50.00m,
|
|
Name = "Test",
|
|
Memo = "Test",
|
|
AccountId = 1
|
|
};
|
|
context.Transactions.Add(transaction);
|
|
await context.SaveChangesAsync();
|
|
|
|
// Act
|
|
var result = await service.DeleteAccountAsync(1);
|
|
|
|
// Assert
|
|
Assert.False(result.Success);
|
|
Assert.Single(context.Accounts);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAccountDetailsAsync_ReturnsFullDetails_WithCardsAndCounts()
|
|
{
|
|
// Arrange
|
|
using var context = DbContextHelper.CreateInMemoryContext();
|
|
var service = new AccountService(context);
|
|
|
|
var account = new Account
|
|
{
|
|
Id = 1,
|
|
Institution = "Test Bank",
|
|
AccountType = AccountType.Checking,
|
|
Last4 = "1234",
|
|
Owner = "Test Owner"
|
|
};
|
|
context.Accounts.Add(account);
|
|
|
|
var card = new Card
|
|
{
|
|
Id = 1,
|
|
AccountId = 1,
|
|
Issuer = "VISA",
|
|
Last4 = "9999",
|
|
Owner = "Test Owner"
|
|
};
|
|
context.Cards.Add(card);
|
|
|
|
var transaction = new Transaction
|
|
{
|
|
Date = DateTime.Now,
|
|
Amount = -50.00m,
|
|
Name = "Test",
|
|
Memo = "Test",
|
|
AccountId = 1,
|
|
CardId = 1
|
|
};
|
|
context.Transactions.Add(transaction);
|
|
await context.SaveChangesAsync();
|
|
|
|
// Act
|
|
var result = await service.GetAccountDetailsAsync(1);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(1, result.Account.Id);
|
|
Assert.Single(result.Cards);
|
|
Assert.Equal(1, result.Cards[0].TransactionCount);
|
|
Assert.Equal(1, result.TransactionCount);
|
|
}
|
|
}
|