Test: add comprehensive unit test project for services

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>
This commit is contained in:
AJ
2025-10-26 00:01:28 -04:00
parent f8bb5d5a82
commit af4a638b81
10 changed files with 1679 additions and 0 deletions

View File

@@ -0,0 +1,229 @@
using MoneyMap.Models;
using MoneyMap.Services;
using MoneyMap.Tests.TestHelpers;
using Xunit;
namespace MoneyMap.Tests.Services;
public class TransactionServiceTests
{
[Fact]
public async Task IsDuplicateAsync_ReturnsFalse_WhenTransactionDoesNotExist()
{
// Arrange
using var context = DbContextHelper.CreateInMemoryContext();
var service = new TransactionService(context);
var transaction = new Transaction
{
Date = DateTime.Now,
Amount = -50.00m,
Name = "Test Store",
Memo = "Test purchase",
AccountId = 1,
CardId = 1
};
// Act
var result = await service.IsDuplicateAsync(transaction);
// Assert
Assert.False(result);
}
[Fact]
public async Task IsDuplicateAsync_ReturnsTrue_WhenExactDuplicateExists()
{
// Arrange
using var context = DbContextHelper.CreateInMemoryContext();
var service = new TransactionService(context);
// Add an account first (required for transaction)
var account = new Account
{
Id = 1,
Institution = "Test Bank",
AccountType = AccountType.Checking,
Last4 = "1234",
Owner = "Test Owner"
};
context.Accounts.Add(account);
var existingTransaction = new Transaction
{
Date = new DateTime(2025, 1, 15),
Amount = -50.00m,
Name = "Test Store",
Memo = "Test purchase",
AccountId = 1,
CardId = 1
};
context.Transactions.Add(existingTransaction);
await context.SaveChangesAsync();
var duplicateTransaction = new Transaction
{
Date = new DateTime(2025, 1, 15),
Amount = -50.00m,
Name = "Test Store",
Memo = "Test purchase",
AccountId = 1,
CardId = 1
};
// Act
var result = await service.IsDuplicateAsync(duplicateTransaction);
// Assert
Assert.True(result);
}
[Fact]
public async Task IsDuplicateAsync_ReturnsFalse_WhenAmountDiffers()
{
// Arrange
using var context = DbContextHelper.CreateInMemoryContext();
var service = new TransactionService(context);
var account = new Account
{
Id = 1,
Institution = "Test Bank",
AccountType = AccountType.Checking,
Last4 = "1234",
Owner = "Test Owner"
};
context.Accounts.Add(account);
var existingTransaction = new Transaction
{
Date = new DateTime(2025, 1, 15),
Amount = -50.00m,
Name = "Test Store",
Memo = "Test purchase",
AccountId = 1,
CardId = 1
};
context.Transactions.Add(existingTransaction);
await context.SaveChangesAsync();
var differentTransaction = new Transaction
{
Date = new DateTime(2025, 1, 15),
Amount = -51.00m, // Different amount
Name = "Test Store",
Memo = "Test purchase",
AccountId = 1,
CardId = 1
};
// Act
var result = await service.IsDuplicateAsync(differentTransaction);
// Assert
Assert.False(result);
}
[Fact]
public async Task GetTransactionByIdAsync_ReturnsNull_WhenTransactionDoesNotExist()
{
// Arrange
using var context = DbContextHelper.CreateInMemoryContext();
var service = new TransactionService(context);
// Act
var result = await service.GetTransactionByIdAsync(999);
// Assert
Assert.Null(result);
}
[Fact]
public async Task GetTransactionByIdAsync_ReturnsTransaction_WhenExists()
{
// Arrange
using var context = DbContextHelper.CreateInMemoryContext();
var service = new TransactionService(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
{
Id = 1,
Date = DateTime.Now,
Amount = -50.00m,
Name = "Test Store",
Memo = "Test purchase",
AccountId = 1
};
context.Transactions.Add(transaction);
await context.SaveChangesAsync();
// Act
var result = await service.GetTransactionByIdAsync(1);
// Assert
Assert.NotNull(result);
Assert.Equal("Test Store", result.Name);
Assert.Equal(-50.00m, result.Amount);
}
[Fact]
public async Task DeleteTransactionAsync_ReturnsTrue_WhenTransactionExists()
{
// Arrange
using var context = DbContextHelper.CreateInMemoryContext();
var service = new TransactionService(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
{
Id = 1,
Date = DateTime.Now,
Amount = -50.00m,
Name = "Test Store",
Memo = "Test purchase",
AccountId = 1
};
context.Transactions.Add(transaction);
await context.SaveChangesAsync();
// Act
var result = await service.DeleteTransactionAsync(1);
// Assert
Assert.True(result);
Assert.Empty(context.Transactions);
}
[Fact]
public async Task DeleteTransactionAsync_ReturnsFalse_WhenTransactionDoesNotExist()
{
// Arrange
using var context = DbContextHelper.CreateInMemoryContext();
var service = new TransactionService(context);
// Act
var result = await service.DeleteTransactionAsync(999);
// Assert
Assert.False(result);
}
}