Add 4 integration tests
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
using Imprink.Application.Commands.Categories;
|
||||
using Imprink.Application.Dtos;
|
||||
using Imprink.Domain.Entities;
|
||||
using Imprink.Domain.Repositories;
|
||||
using Imprink.Infrastructure;
|
||||
using Imprink.Infrastructure.Database;
|
||||
using Imprink.Infrastructure.Repositories;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace Imprink.Application.Tests;
|
||||
|
||||
public class CreateCategoryHandlerIntegrationTest : IDisposable
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly CreateCategoryHandler _handler;
|
||||
private readonly SqliteConnection _connection;
|
||||
|
||||
public CreateCategoryHandlerIntegrationTest()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
_connection = new SqliteConnection("Data Source=:memory:");
|
||||
_connection.Open();
|
||||
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
options.UseSqlite(_connection));
|
||||
|
||||
services.AddScoped<ICategoryRepository, CategoryRepository>();
|
||||
services.AddScoped<IProductRepository, ProductRepository>();
|
||||
services.AddScoped<IProductVariantRepository, ProductVariantRepository>();
|
||||
services.AddScoped<IUserRepository, UserRepository>();
|
||||
services.AddScoped<IUserRoleRepository, UserRoleRepository>();
|
||||
services.AddScoped<IRoleRepository, RoleRepository>();
|
||||
services.AddScoped<IOrderRepository, OrderRepository>();
|
||||
services.AddScoped<IOrderItemRepository, OrderItemRepository>();
|
||||
|
||||
services.AddScoped<IUnitOfWork, UnitOfWork>();
|
||||
services.AddScoped<CreateCategoryHandler>();
|
||||
|
||||
_serviceProvider = services.BuildServiceProvider();
|
||||
_context = _serviceProvider.GetRequiredService<ApplicationDbContext>();
|
||||
_handler = _serviceProvider.GetRequiredService<CreateCategoryHandler>();
|
||||
|
||||
_context.Database.EnsureCreated();
|
||||
}
|
||||
|
||||
private async Task CleanDatabase()
|
||||
{
|
||||
_context.Categories.RemoveRange(_context.Categories);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ValidCreateCategoryCommand_PersistsToDatabase()
|
||||
{
|
||||
await CleanDatabase();
|
||||
|
||||
// Arrange
|
||||
var command = new CreateCategoryCommand
|
||||
{
|
||||
Name = "Electronics",
|
||||
Description = "Electronic devices and gadgets",
|
||||
ImageUrl = "https://example.com/electronics.jpg",
|
||||
SortOrder = 1,
|
||||
IsActive = true,
|
||||
ParentCategoryId = null
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.NotEqual(Guid.Empty, result.Id);
|
||||
Assert.Equal(command.Name, result.Name);
|
||||
Assert.Equal(command.Description, result.Description);
|
||||
Assert.Equal(command.ImageUrl, result.ImageUrl);
|
||||
Assert.Equal(command.SortOrder, result.SortOrder);
|
||||
Assert.Equal(command.IsActive, result.IsActive);
|
||||
Assert.Equal(command.ParentCategoryId, result.ParentCategoryId);
|
||||
Assert.NotNull(result.CreatedAt);
|
||||
Assert.NotNull(result.ModifiedAt);
|
||||
|
||||
var savedCategory = await _context.Categories
|
||||
.FirstOrDefaultAsync(c => c.Id == result.Id);
|
||||
|
||||
Assert.NotNull(savedCategory);
|
||||
Assert.Equal(command.Name, savedCategory.Name);
|
||||
Assert.Equal(command.Description, savedCategory.Description);
|
||||
Assert.Equal(command.ImageUrl, savedCategory.ImageUrl);
|
||||
Assert.Equal(command.SortOrder, savedCategory.SortOrder);
|
||||
Assert.Equal(command.IsActive, savedCategory.IsActive);
|
||||
Assert.Equal(command.ParentCategoryId, savedCategory.ParentCategoryId);
|
||||
Assert.NotNull(savedCategory.CreatedAt);
|
||||
Assert.NotNull(savedCategory.ModifiedAt);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ValidCreateCategoryCommandWithParent_PersistsWithCorrectParentRelationship()
|
||||
{
|
||||
await CleanDatabase();
|
||||
|
||||
// Arrange
|
||||
var parentCategory = new Category
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Parent Category",
|
||||
Description = "Parent category description",
|
||||
SortOrder = 1,
|
||||
IsActive = true,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
ModifiedAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_context.Categories.Add(parentCategory);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var command = new CreateCategoryCommand
|
||||
{
|
||||
Name = "Child Electronics",
|
||||
Description = "Electronic devices and gadgets under parent",
|
||||
ImageUrl = "https://example.com/child-electronics.jpg",
|
||||
SortOrder = 2,
|
||||
IsActive = true,
|
||||
ParentCategoryId = parentCategory.Id
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(parentCategory.Id, result.ParentCategoryId);
|
||||
|
||||
var savedCategory = await _context.Categories
|
||||
.Include(c => c.ParentCategory)
|
||||
.FirstOrDefaultAsync(c => c.Id == result.Id);
|
||||
|
||||
Assert.NotNull(savedCategory);
|
||||
Assert.NotNull(savedCategory.ParentCategory);
|
||||
Assert.Equal(parentCategory.Id, savedCategory.ParentCategory.Id);
|
||||
Assert.Equal(parentCategory.Name, savedCategory.ParentCategory.Name);
|
||||
|
||||
var parentWithChildren = await _context.Categories
|
||||
.Include(c => c.SubCategories)
|
||||
.FirstOrDefaultAsync(c => c.Id == parentCategory.Id);
|
||||
|
||||
Assert.NotNull(parentWithChildren);
|
||||
Assert.Contains(parentWithChildren.SubCategories, sc => sc.Id == result.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_CreateMultipleCategories_AllPersistCorrectly()
|
||||
{
|
||||
await CleanDatabase();
|
||||
|
||||
// Arrange
|
||||
var commands = new[]
|
||||
{
|
||||
new CreateCategoryCommand
|
||||
{
|
||||
Name = "Category 1",
|
||||
Description = "First category",
|
||||
SortOrder = 1,
|
||||
IsActive = true
|
||||
},
|
||||
new CreateCategoryCommand
|
||||
{
|
||||
Name = "Category 2",
|
||||
Description = "Second category",
|
||||
SortOrder = 2,
|
||||
IsActive = false
|
||||
}
|
||||
};
|
||||
|
||||
// Act
|
||||
var results = new List<CategoryDto>();
|
||||
foreach (var command in commands)
|
||||
{
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
results.Add(result);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, results.Count);
|
||||
|
||||
var categoriesInDb = await _context.Categories.ToListAsync();
|
||||
|
||||
Assert.Equal(2, categoriesInDb.Count);
|
||||
|
||||
foreach (var result in results)
|
||||
{
|
||||
var savedCategory = categoriesInDb.First(c => c.Id == result.Id);
|
||||
Assert.Equal(result.Name, savedCategory.Name);
|
||||
Assert.Equal(result.Description, savedCategory.Description);
|
||||
Assert.Equal(result.IsActive, savedCategory.IsActive);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_TransactionFailure_RollsBackCorrectly()
|
||||
{
|
||||
await CleanDatabase();
|
||||
|
||||
// Arrange
|
||||
var command = new CreateCategoryCommand
|
||||
{
|
||||
Name = "Test Category",
|
||||
Description = "Test description",
|
||||
SortOrder = 1,
|
||||
IsActive = true
|
||||
};
|
||||
|
||||
var initialCount = await _context.Categories.CountAsync();
|
||||
|
||||
var handler = _serviceProvider.GetRequiredService<CreateCategoryHandler>();
|
||||
|
||||
var result = await handler.Handle(command, CancellationToken.None);
|
||||
|
||||
Assert.NotNull(result);
|
||||
|
||||
var finalCount = await _context.Categories.CountAsync();
|
||||
Assert.Equal(initialCount + 1, finalCount);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
_context.Dispose();
|
||||
_connection.Close();
|
||||
_connection.Dispose();
|
||||
_serviceProvider.GetService<IServiceScope>()?.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -8,14 +8,18 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="xunit" Version="2.6.6" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
|
||||
<PackageReference Include="MediatR" Version="12.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0-preview.1.24081.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
@@ -28,6 +32,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Imprink.Application\Imprink.Application.csproj" />
|
||||
<ProjectReference Include="..\..\src\Imprink.Domain\Imprink.Domain.csproj" />
|
||||
<ProjectReference Include="..\..\src\Imprink.Infrastructure\Imprink.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user