namespace BudgetApp.Tests.Application; using BudgetApp.Application.Services; using BudgetApp.Domain.Interfaces; using BudgetApp.Domain.Models; using Moq; using Xunit; public class BudgetServiceTests { private readonly Mock _mockRepository; private readonly BudgetService _service; public BudgetServiceTests() { _mockRepository = new Mock(); _service = new BudgetService(_mockRepository.Object); } [Fact] public async Task CreateBaseBudgetAsync_WithValidParameters_CreatesAndSavesBudget() { // Arrange var name = "Grocery"; var initialBalance = new Money(100m, "USD"); _mockRepository.Setup(r => r.SaveAsync(It.IsAny())) .Returns(Task.CompletedTask); // Act var budget = await _service.CreateBaseBudgetAsync(name, initialBalance); // Assert Assert.NotNull(budget); Assert.Equal(name, budget.Name); Assert.Equal(100m, budget.Balance.Amount); _mockRepository.Verify(r => r.SaveAsync(It.IsAny()), Times.Once); } [Fact] public async Task CreateBaseBudgetAsync_WithNullName_ThrowsException() { // Arrange var initialBalance = new Money(100m, "USD"); // Act & Assert await Assert.ThrowsAsync(() => _service.CreateBaseBudgetAsync(null!, initialBalance)); } [Fact] public async Task CreateGoalBudgetAsync_WithValidParameters_CreatesAndSavesBudget() { // Arrange var name = "Car Purchase"; var initialBalance = new Money(0m, "USD"); var goalAmount = new Money(30000m, "USD"); var targetDate = DateTime.Now.AddYears(3); var periodicContribution = new Money(1000m, "USD"); var contributionPeriod = TimeSpan.FromDays(30); _mockRepository.Setup(r => r.SaveAsync(It.IsAny())) .Returns(Task.CompletedTask); // Act var budget = await _service.CreateGoalBudgetAsync( name, initialBalance, goalAmount, targetDate, periodicContribution, contributionPeriod); // Assert Assert.NotNull(budget); Assert.Equal(name, budget.Name); Assert.Equal(30000m, budget.GoalAmount.Amount); _mockRepository.Verify(r => r.SaveAsync(It.IsAny()), Times.Once); } [Fact] public async Task GetBudgetByIdAsync_ReturnsBudget() { // Arrange var budgetId = Guid.NewGuid(); var budget = new BaseBudget("Grocery", new Money(100m, "USD")); _mockRepository.Setup(r => r.GetByIdAsync(budgetId)) .ReturnsAsync(budget); // Act var result = await _service.GetBudgetByIdAsync(budgetId); // Assert Assert.NotNull(result); Assert.Equal(budget.Id, result.Id); } [Fact] public async Task GetAllBudgetsAsync_ReturnsAllBudgets() { // Arrange var budgets = new List { new BaseBudget("Grocery", new Money(100m, "USD")), new BaseBudget("Medical", new Money(200m, "USD")) }; _mockRepository.Setup(r => r.GetAllAsync()) .ReturnsAsync(budgets); // Act var result = await _service.GetAllBudgetsAsync(); // Assert Assert.Equal(2, result.Count()); } [Fact] public async Task GetBudgetBalanceAsync_ReturnsBalance() { // Arrange var budgetId = Guid.NewGuid(); var budget = new BaseBudget("Grocery", new Money(100m, "USD")); _mockRepository.Setup(r => r.GetByIdAsync(budgetId)) .ReturnsAsync(budget); // Act var balance = await _service.GetBudgetBalanceAsync(budgetId); // Assert Assert.NotNull(balance); Assert.Equal(100m, balance.Amount); } [Fact] public async Task GetTotalBudgetBalanceAsync_ReturnsSumOfAllBudgets() { // Arrange var budgets = new List { new BaseBudget("Grocery", new Money(100m, "USD")), new BaseBudget("Medical", new Money(200m, "USD")) }; _mockRepository.Setup(r => r.GetAllAsync()) .ReturnsAsync(budgets); // Act var total = await _service.GetTotalBudgetBalanceAsync("USD"); // Assert Assert.Equal(300m, total.Amount); } }