using FluentAssertions; using MiningService.API.Application.Commands; using MiningService.Domain.AggregatesModel.CircleAggregate; using MiningService.Domain.AggregatesModel.MinerAggregate; using NSubstitute; using Xunit; namespace MiningService.UnitTests.Application.Commands; /// /// EN: Unit tests for Circle Command Handlers. /// VI: Unit tests cho Circle Command Handlers. /// public class CircleCommandHandlerTests { private readonly ICircleRepository _circleRepository; private readonly IMinerRepository _minerRepository; public CircleCommandHandlerTests() { _circleRepository = Substitute.For(); _minerRepository = Substitute.For(); } #region CreateCircleCommandHandler Tests [Fact] public async Task CreateCircle_ValidInput_CreatesNewCircle() { // Arrange var userId = Guid.NewGuid(); var miner = Miner.Create(userId); var command = new CreateCircleCommand(userId, "Test Circle"); var handler = new CreateCircleCommandHandler(_circleRepository, _minerRepository); _minerRepository.GetByUserIdAsync(userId, Arg.Any()) .Returns(miner); _circleRepository.UnitOfWork.SaveEntitiesAsync(Arg.Any()) .Returns(true); // Act var result = await handler.Handle(command, CancellationToken.None); // Assert result.Should().NotBeNull(); result.CircleId.Should().NotBeEmpty(); _circleRepository.Received(1).Add(Arg.Is(c => c.Name == "Test Circle")); } [Fact] public async Task CreateCircle_MinerAlreadyInCircle_ThrowsException() { // Arrange var userId = Guid.NewGuid(); var miner = Miner.Create(userId); miner.JoinCircle(Guid.NewGuid()); // Already in a circle var command = new CreateCircleCommand(userId, "New Circle"); var handler = new CreateCircleCommandHandler(_circleRepository, _minerRepository); _minerRepository.GetByUserIdAsync(userId, Arg.Any()) .Returns(miner); // Act & Assert var act = () => handler.Handle(command, CancellationToken.None); await act.Should().ThrowAsync().WithMessage("*already*"); } #endregion #region InviteToCircleCommandHandler Tests [Fact] public async Task InviteToCircle_ValidInput_ReturnsTrue() { // Arrange var ownerId = Guid.NewGuid(); var inviteeId = Guid.NewGuid(); var circle = Circle.Create(ownerId, "Test Circle"); var inviter = Miner.Create(ownerId); var invitee = Miner.Create(inviteeId); var command = new InviteToCircleCommand(ownerId, inviteeId); var handler = new InviteToCircleCommandHandler(_circleRepository, _minerRepository); _circleRepository.GetByOwnerIdAsync(ownerId, Arg.Any()) .Returns(circle); _minerRepository.GetByUserIdAsync(ownerId, Arg.Any()) .Returns(inviter); _minerRepository.GetByUserIdAsync(inviteeId, Arg.Any()) .Returns(invitee); _circleRepository.UnitOfWork.SaveEntitiesAsync(Arg.Any()) .Returns(true); // Act var result = await handler.Handle(command, CancellationToken.None); // Assert result.Should().BeTrue(); } #endregion }