Files
pos-system/services/membership-service-net/tests/MembershipService.UnitTests/Handlers/CreateLevelDefinitionCommandHandlerTests.cs

149 lines
4.7 KiB
C#

using FluentAssertions;
using MembershipService.API.Application.Commands;
using MembershipService.Domain.AggregatesModel.LevelAggregate;
using MembershipService.Domain.SeedWork;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;
namespace MembershipService.UnitTests.Handlers;
/// <summary>
/// EN: Unit tests for CreateLevelDefinitionCommandHandler.
/// VI: Unit tests cho CreateLevelDefinitionCommandHandler.
/// </summary>
public class CreateLevelDefinitionCommandHandlerTests
{
private readonly ILevelDefinitionRepository _repository;
private readonly IUnitOfWork _unitOfWork;
private readonly ILogger<CreateLevelDefinitionCommandHandler> _logger;
private readonly CreateLevelDefinitionCommandHandler _handler;
public CreateLevelDefinitionCommandHandlerTests()
{
_repository = Substitute.For<ILevelDefinitionRepository>();
_unitOfWork = Substitute.For<IUnitOfWork>();
_logger = Substitute.For<ILogger<CreateLevelDefinitionCommandHandler>>();
_repository.UnitOfWork.Returns(_unitOfWork);
_handler = new CreateLevelDefinitionCommandHandler(_repository, _logger);
}
[Fact]
public async Task Handle_ValidCommand_ShouldCreateLevelDefinition()
{
// Arrange
var command = new CreateLevelDefinitionCommand
{
LevelNumber = 6,
Name = "Master",
RequiredExp = 2000,
Description = "Master level",
BadgeColor = "#8B00FF"
};
_repository.ExistsByLevelNumberAsync(command.LevelNumber)
.Returns(false);
_repository.Add(Arg.Any<LevelDefinition>())
.Returns(x => x.Arg<LevelDefinition>());
_unitOfWork.SaveEntitiesAsync(Arg.Any<CancellationToken>())
.Returns(true);
// Act
var result = await _handler.Handle(command, CancellationToken.None);
// Assert
result.Should().NotBeNull();
result.LevelNumber.Should().Be(6);
result.Name.Should().Be("Master");
result.RequiredExp.Should().Be(2000);
result.Id.Should().NotBeEmpty();
_repository.Received(1).Add(Arg.Any<LevelDefinition>());
await _unitOfWork.Received(1).SaveEntitiesAsync(Arg.Any<CancellationToken>());
}
[Fact]
public async Task Handle_DuplicateLevelNumber_ShouldThrowInvalidOperationException()
{
// Arrange
var command = new CreateLevelDefinitionCommand
{
LevelNumber = 1,
Name = "Duplicate",
RequiredExp = 0
};
_repository.ExistsByLevelNumberAsync(command.LevelNumber)
.Returns(true);
// Act
var act = () => _handler.Handle(command, CancellationToken.None);
// Assert
await act.Should().ThrowAsync<InvalidOperationException>()
.WithMessage("*already exists*");
_repository.DidNotReceive().Add(Arg.Any<LevelDefinition>());
}
[Fact]
public async Task Handle_WithOptionalFields_ShouldCreateWithAllFields()
{
// Arrange
var command = new CreateLevelDefinitionCommand
{
LevelNumber = 7,
Name = "Legend",
RequiredExp = 5000,
Description = "Legend tier for elite members",
IconUrl = "https://example.com/legend.png",
BadgeColor = "#FFD700"
};
_repository.ExistsByLevelNumberAsync(command.LevelNumber)
.Returns(false);
_repository.Add(Arg.Any<LevelDefinition>())
.Returns(x => x.Arg<LevelDefinition>());
_unitOfWork.SaveEntitiesAsync(Arg.Any<CancellationToken>())
.Returns(true);
// Act
var result = await _handler.Handle(command, CancellationToken.None);
// Assert
result.Should().NotBeNull();
result.LevelNumber.Should().Be(7);
result.Name.Should().Be("Legend");
result.RequiredExp.Should().Be(5000);
}
[Fact]
public async Task Handle_MinimalCommand_ShouldCreateWithDefaults()
{
// Arrange
var command = new CreateLevelDefinitionCommand
{
LevelNumber = 8,
Name = "Minimal",
RequiredExp = 100
};
_repository.ExistsByLevelNumberAsync(command.LevelNumber)
.Returns(false);
_repository.Add(Arg.Any<LevelDefinition>())
.Returns(x => x.Arg<LevelDefinition>());
_unitOfWork.SaveEntitiesAsync(Arg.Any<CancellationToken>())
.Returns(true);
// Act
var result = await _handler.Handle(command, CancellationToken.None);
// Assert
result.Should().NotBeNull();
result.LevelNumber.Should().Be(8);
result.Name.Should().Be("Minimal");
}
}