littleshop/LittleShop.Tests/Unit/CategoryServiceTests.cs
sysadmin 1f7c0af497 Add LittleShop.Client SDK library with complete API wrapper
Features:
- Complete .NET client SDK for LittleShop API
- JWT authentication with automatic token management
- Catalog service for products and categories
- Order service with payment creation
- Retry policies using Polly for resilience
- Error handling middleware
- Dependency injection support
- Comprehensive documentation and examples

SDK Components:
- Authentication service with token refresh
- Strongly-typed models for all API responses
- HTTP handlers for retry and error handling
- Extension methods for easy DI registration
- Example console application demonstrating usage

Test Updates:
- Fixed test compilation errors
- Updated test data builders for new models
- Corrected service constructor dependencies
- Fixed enum value changes (PaymentStatus, OrderStatus)

Documentation:
- Complete project README with features and usage
- Client SDK README with detailed examples
- API endpoint documentation
- Security considerations
- Deployment guidelines

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-20 18:15:35 +01:00

254 lines
7.1 KiB
C#

using FluentAssertions;
using LittleShop.Data;
using LittleShop.DTOs;
using LittleShop.Models;
using LittleShop.Services;
using Microsoft.EntityFrameworkCore;
using Moq;
using AutoMapper;
using Xunit;
using LittleShop.Mapping;
namespace LittleShop.Tests.Unit;
public class CategoryServiceTests : IDisposable
{
private readonly LittleShopContext _context;
private readonly ICategoryService _categoryService;
public CategoryServiceTests()
{
// Set up in-memory database
var options = new DbContextOptionsBuilder<LittleShopContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;
_context = new LittleShopContext(options);
// Create service
_categoryService = new CategoryService(_context);
}
[Fact]
public async Task GetAllCategoriesAsync_ReturnsAllCategories()
{
// Arrange
var categories = new[]
{
new Category { Id = Guid.NewGuid(), Name = "Category 1", Description = "Desc 1", IsActive = true },
new Category { Id = Guid.NewGuid(), Name = "Category 2", Description = "Desc 2", IsActive = true },
new Category { Id = Guid.NewGuid(), Name = "Category 3", Description = "Desc 3", IsActive = false }
};
_context.Categories.AddRange(categories);
await _context.SaveChangesAsync();
// Act
var result = await _categoryService.GetAllCategoriesAsync();
// Assert
result.Should().HaveCount(3);
result.Should().Contain(c => c.Name == "Category 1");
result.Should().Contain(c => c.Name == "Category 2");
result.Should().Contain(c => c.Name == "Category 3");
}
[Fact]
public async Task GetCategoryByIdAsync_WithValidId_ReturnsCategory()
{
// Arrange
var categoryId = Guid.NewGuid();
var category = new Category
{
Id = categoryId,
Name = "Test Category",
Description = "Test Description",
IsActive = true
};
_context.Categories.Add(category);
await _context.SaveChangesAsync();
// Act
var result = await _categoryService.GetCategoryByIdAsync(categoryId);
// Assert
result.Should().NotBeNull();
result!.Id.Should().Be(categoryId);
result.Name.Should().Be("Test Category");
result.Description.Should().Be("Test Description");
}
[Fact]
public async Task GetCategoryByIdAsync_WithInvalidId_ReturnsNull()
{
// Arrange
var invalidId = Guid.NewGuid();
// Act
var result = await _categoryService.GetCategoryByIdAsync(invalidId);
// Assert
result.Should().BeNull();
}
[Fact]
public async Task CreateCategoryAsync_WithValidData_CreatesCategory()
{
// Arrange
var createDto = new CreateCategoryDto
{
Name = "New Category",
Description = "New Description"
};
// Act
var result = await _categoryService.CreateCategoryAsync(createDto);
// Assert
result.Should().NotBeNull();
result.Name.Should().Be("New Category");
result.Description.Should().Be("New Description");
result.IsActive.Should().BeTrue();
// Verify in database
var dbCategory = await _context.Categories.FindAsync(result.Id);
dbCategory.Should().NotBeNull();
dbCategory!.Name.Should().Be("New Category");
}
[Fact]
public async Task UpdateCategoryAsync_WithValidData_UpdatesCategory()
{
// Arrange
var categoryId = Guid.NewGuid();
var category = new Category
{
Id = categoryId,
Name = "Original Name",
Description = "Original Description",
IsActive = true
};
_context.Categories.Add(category);
await _context.SaveChangesAsync();
var updateDto = new UpdateCategoryDto
{
Name = "Updated Name",
Description = "Updated Description",
IsActive = false
};
// Act
var result = await _categoryService.UpdateCategoryAsync(categoryId, updateDto);
// Assert
result.Should().BeTrue();
// Verify in database
var dbCategory = await _context.Categories.FindAsync(categoryId);
dbCategory!.Name.Should().Be("Updated Name");
dbCategory.Description.Should().Be("Updated Description");
dbCategory.IsActive.Should().BeFalse();
}
[Fact]
public async Task UpdateCategoryAsync_WithInvalidId_ReturnsFalse()
{
// Arrange
var invalidId = Guid.NewGuid();
var updateDto = new UpdateCategoryDto
{
Name = "Updated Name",
Description = "Updated Description",
IsActive = true
};
// Act
var result = await _categoryService.UpdateCategoryAsync(invalidId, updateDto);
// Assert
result.Should().BeFalse();
}
[Fact]
public async Task DeleteCategoryAsync_WithValidId_DeletesCategory()
{
// Arrange
var categoryId = Guid.NewGuid();
var category = new Category
{
Id = categoryId,
Name = "To Delete",
Description = "Will be deleted",
IsActive = true
};
_context.Categories.Add(category);
await _context.SaveChangesAsync();
// Act
var result = await _categoryService.DeleteCategoryAsync(categoryId);
// Assert
result.Should().BeTrue();
// Verify in database
var dbCategory = await _context.Categories.FindAsync(categoryId);
dbCategory.Should().BeNull();
}
[Fact]
public async Task DeleteCategoryAsync_WithInvalidId_ReturnsFalse()
{
// Arrange
var invalidId = Guid.NewGuid();
// Act
var result = await _categoryService.DeleteCategoryAsync(invalidId);
// Assert
result.Should().BeFalse();
}
[Fact]
public async Task DeleteCategoryAsync_WithProductsAttached_ThrowsException()
{
// Arrange
var categoryId = Guid.NewGuid();
var category = new Category
{
Id = categoryId,
Name = "Category with Products",
Description = "Has products",
IsActive = true
};
var product = new Product
{
Id = Guid.NewGuid(),
Name = "Product",
Description = "Product in category",
Price = 10.00m,
CategoryId = categoryId,
IsActive = true,
Weight = 1,
WeightUnit = Enums.ProductWeightUnit.Kilograms
};
_context.Categories.Add(category);
_context.Products.Add(product);
await _context.SaveChangesAsync();
// Act & Assert
await Assert.ThrowsAsync<DbUpdateException>(async () =>
{
await _categoryService.DeleteCategoryAsync(categoryId);
});
}
public void Dispose()
{
_context.Dispose();
}
}