Files
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

115 lines
4.0 KiB
C#

namespace WalletService.UnitTests.Application;
using FluentAssertions;
using Microsoft.Extensions.Logging;
using NSubstitute;
using WalletService.API.Application.Commands;
using WalletService.Domain.AggregatesModel.WalletAggregate;
using WalletService.Domain.Exceptions;
using WalletService.Domain.SeedWork;
using Xunit;
public class EscrowCommandHandlersTests
{
private readonly IWalletRepository _walletRepository;
private readonly ILogger<CreateHoldCommandHandler> _createLogger;
private readonly ILogger<ExecuteHoldCommandHandler> _executeLogger;
private readonly IUnitOfWork _unitOfWork;
public EscrowCommandHandlersTests()
{
_walletRepository = Substitute.For<IWalletRepository>();
_unitOfWork = Substitute.For<IUnitOfWork>();
_walletRepository.UnitOfWork.Returns(_unitOfWork);
_unitOfWork.SaveEntitiesAsync(Arg.Any<CancellationToken>()).Returns(true);
_createLogger = Substitute.For<ILogger<CreateHoldCommandHandler>>();
_executeLogger = Substitute.For<ILogger<ExecuteHoldCommandHandler>>();
}
[Fact]
public async Task CreateHold_ValidCommand_ShouldSucceed()
{
// Arrange
var walletId = Guid.NewGuid();
var userId = Guid.NewGuid();
var wallet = new Wallet(userId, CurrencyType.VND);
wallet.Deposit(1000m, CurrencyType.VND, "Init");
// Mock repository to return our wallet when searching by UserId (CreateHoldCommand uses UserId)
_walletRepository.GetByUserIdAsync(userId).Returns(wallet);
var handler = new CreateHoldCommandHandler(_walletRepository, _createLogger);
var command = new CreateHoldCommand(
userId,
100m,
"VND",
"CAMPAIGN",
Guid.NewGuid(),
"Test Hold");
// Act
var result = await handler.Handle(command, CancellationToken.None);
// Assert
result.Should().NotBeNull();
result.RemainingAmount.Should().Be(100m);
wallet.GetBalance(CurrencyType.VND).Should().Be(900m);
_walletRepository.Received(1).Update(wallet);
await _unitOfWork.Received(1).SaveEntitiesAsync(Arg.Any<CancellationToken>());
}
[Fact]
public async Task ExecuteHold_ValidCommand_ShouldSucceed()
{
// Arrange
var userId = Guid.NewGuid();
var wallet = new Wallet(userId, CurrencyType.VND);
wallet.Deposit(1000m, CurrencyType.VND, "Init");
var hold = wallet.Hold(100m, CurrencyType.VND, "REF", Guid.NewGuid(), "Desc");
// Mock repository to return wallet by ID (ExecuteHoldCommand uses WalletId)
_walletRepository.GetByIdAsync(wallet.Id).Returns(wallet);
var handler = new ExecuteHoldCommandHandler(_walletRepository, _executeLogger);
var command = new ExecuteHoldCommand(
wallet.Id,
hold.Id,
40m,
"EXEC_REF");
// Act
var result = await handler.Handle(command, CancellationToken.None);
// Assert
result.ExecutedAmount.Should().Be(40m);
result.RemainingAmount.Should().Be(60m);
await _unitOfWork.Received(1).SaveEntitiesAsync(Arg.Any<CancellationToken>());
}
[Fact]
public async Task ExecuteHold_InsufficientHoldAmount_ShouldThrow()
{
// Arrange
var userId = Guid.NewGuid();
var wallet = new Wallet(userId, CurrencyType.VND);
wallet.Deposit(1000m, CurrencyType.VND, "Init");
var hold = wallet.Hold(100m, CurrencyType.VND, "REF", Guid.NewGuid(), "Desc");
_walletRepository.GetByIdAsync(wallet.Id).Returns(wallet);
var handler = new ExecuteHoldCommandHandler(_walletRepository, _executeLogger);
var command = new ExecuteHoldCommand(
wallet.Id,
hold.Id,
150m, // Try to execute more than held
"EXEC_REF");
// Act & Assert
await Assert.ThrowsAsync<WalletDomainException>(() =>
handler.Handle(command, CancellationToken.None));
}
}