using FluentAssertions; using MiningService.API.Application.Commands; using MiningService.Domain.AggregatesModel.MinerAggregate; using MiningService.Domain.Exceptions; using MiningService.Domain.SeedWork; using NSubstitute; using Xunit; namespace MiningService.UnitTests.Application.Commands; /// /// EN: Unit tests for StartMiningCommandHandler. /// VI: Unit tests cho StartMiningCommandHandler. /// public class StartMiningCommandHandlerTests { private readonly IMinerRepository _minerRepository; private readonly IUnitOfWork _unitOfWork; private readonly StartMiningCommandHandler _handler; public StartMiningCommandHandlerTests() { _unitOfWork = Substitute.For(); _unitOfWork.SaveEntitiesAsync(Arg.Any()).Returns(true); _minerRepository = Substitute.For(); _minerRepository.UnitOfWork.Returns(_unitOfWork); _handler = new StartMiningCommandHandler(_minerRepository); } [Fact] public async Task Handle_ExistingMiner_StartsSession() { // Arrange var userId = Guid.NewGuid(); var miner = Miner.Create(userId); var command = new StartMiningCommand(userId); _minerRepository.GetByUserIdAsync(userId, Arg.Any()) .Returns(miner); // Act var result = await _handler.Handle(command, CancellationToken.None); // Assert result.Should().NotBeNull(); result.SessionId.Should().NotBeEmpty(); result.HourlyRate.Should().BeGreaterThan(0); await _unitOfWork.Received(1).SaveEntitiesAsync(Arg.Any()); } [Fact] public async Task Handle_NewUser_CreatesMinerAndStartsSession() { // Arrange var userId = Guid.NewGuid(); var command = new StartMiningCommand(userId); _minerRepository.GetByUserIdAsync(userId, Arg.Any()) .Returns((Miner?)null); // Act var result = await _handler.Handle(command, CancellationToken.None); // Assert result.Should().NotBeNull(); result.SessionId.Should().NotBeEmpty(); _minerRepository.Received(1).Add(Arg.Is(m => m.UserId == userId)); } [Fact] public async Task Handle_SuspendedMiner_ThrowsException() { // Arrange var userId = Guid.NewGuid(); var miner = Miner.Create(userId); miner.Suspend(); var command = new StartMiningCommand(userId); _minerRepository.GetByUserIdAsync(userId, Arg.Any()) .Returns(miner); // Act & Assert await Assert.ThrowsAsync(() => _handler.Handle(command, CancellationToken.None)); } [Fact] public async Task Handle_AlreadyMining_ThrowsException() { // Arrange var userId = Guid.NewGuid(); var miner = Miner.Create(userId); miner.StartMiningSession(); var command = new StartMiningCommand(userId); _minerRepository.GetByUserIdAsync(userId, Arg.Any()) .Returns(miner); // Act & Assert await Assert.ThrowsAsync(() => _handler.Handle(command, CancellationToken.None)); } }