Files
pos-system/services/wallet-service-net/tests/WalletService.UnitTests/Domain/WalletTests.cs

234 lines
6.9 KiB
C#

// EN: Unit tests for Wallet aggregate with multi-currency support
// VI: Unit tests cho Wallet aggregate với hỗ trợ đa tiền tệ
using WalletService.Domain.AggregatesModel.WalletAggregate;
using WalletService.Domain.Exceptions;
using Xunit;
namespace WalletService.UnitTests.Domain;
public class WalletTests
{
private static readonly Guid TestUserId = Guid.NewGuid();
[Fact]
public void Constructor_ShouldCreateWallet_WithZeroBalance()
{
// Arrange & Act
var wallet = new Wallet(TestUserId, CurrencyType.VND);
// Assert
Assert.NotNull(wallet);
Assert.Equal(TestUserId, wallet.UserId);
Assert.Equal(CurrencyType.VND.Id, wallet.DefaultCurrencyTypeId);
Assert.Equal(0, wallet.GetBalance(CurrencyType.VND));
Assert.Equal(WalletStatus.Active, wallet.Status);
}
[Fact]
public void Constructor_ShouldDefaultToVND_WhenNoCurrencyProvided()
{
// Arrange & Act
var wallet = new Wallet(TestUserId);
// Assert
Assert.Equal(CurrencyType.VND.Id, wallet.DefaultCurrencyTypeId);
}
[Fact]
public void Deposit_ShouldIncreaseBalance()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
// Act
wallet.Deposit(100000m, CurrencyType.VND, "Test deposit", "REF001");
// Assert
Assert.Equal(100000m, wallet.GetBalance(CurrencyType.VND));
Assert.Single(wallet.Transactions);
Assert.Equal(TransactionType.Credit, wallet.Transactions.First().Type);
}
[Fact]
public void CreateMoney_ShouldThrow_WhenAmountIsNegative()
{
// Arrange & Act & Assert
// EN: Money constructor throws ArgumentException for negative amounts
// VI: Money constructor ném ArgumentException cho số tiền âm
Assert.Throws<ArgumentException>(() =>
new Money(-100, "VND"));
}
[Fact]
public void Withdraw_ShouldDecreaseBalance()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
wallet.Deposit(100000m, CurrencyType.VND, "Initial deposit", "REF001");
// Act
wallet.Withdraw(50000m, CurrencyType.VND, "Test withdrawal", "REF002");
// Assert
Assert.Equal(50000m, wallet.GetBalance(CurrencyType.VND));
Assert.Equal(2, wallet.Transactions.Count);
}
[Fact]
public void Withdraw_ShouldThrow_WhenInsufficientBalance()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
wallet.Deposit(50000m, CurrencyType.VND, "Initial deposit", "REF001");
// Act & Assert
Assert.Throws<InsufficientBalanceException>(() =>
wallet.Withdraw(100000m, CurrencyType.VND, "Invalid withdrawal"));
}
[Fact]
public void Freeze_ShouldSetStatusToFrozen()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
// Act
wallet.Freeze();
// Assert
Assert.Equal(WalletStatus.Frozen, wallet.Status);
}
[Fact]
public void Unfreeze_ShouldSetStatusToActive()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
wallet.Freeze();
// Act
wallet.Unfreeze();
// Assert
Assert.Equal(WalletStatus.Active, wallet.Status);
}
[Fact]
public void Close_ShouldSetStatusToClosed()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
// Act
wallet.Close();
// Assert
Assert.Equal(WalletStatus.Closed, wallet.Status);
}
[Fact]
public void Close_ShouldThrow_WhenBalanceIsPositive()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
wallet.Deposit(100000m, CurrencyType.VND, "Deposit", "REF001");
// Act & Assert
Assert.Throws<WalletDomainException>(() => wallet.Close());
}
#region Multi-Currency Tests / Tests đa tiền tệ
[Fact]
public void Deposit_ShouldSupportMultipleCurrencies()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
// Act
wallet.Deposit(100000m, CurrencyType.VND, "VND deposit");
wallet.Deposit(100m, CurrencyType.USD, "USD deposit");
wallet.Deposit(1000, CurrencyType.PPoint, "PPoint deposit");
// Assert
Assert.Equal(100000m, wallet.GetBalance(CurrencyType.VND));
Assert.Equal(100m, wallet.GetBalance(CurrencyType.USD));
Assert.Equal(1000, wallet.GetBalance(CurrencyType.PPoint));
Assert.Equal(3, wallet.Balances.Count);
}
[Fact]
public void Exchange_ShouldConvertBetweenCurrencies()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
wallet.Deposit(100000m, CurrencyType.VND, "Initial VND deposit");
// Act - Exchange 100000 VND to PPoint (rate: 1 VND = 0.001 PPoint)
var receivedPoints = wallet.Exchange(100000m, CurrencyType.VND, CurrencyType.PPoint);
// Assert
Assert.Equal(0, wallet.GetBalance(CurrencyType.VND));
Assert.Equal(100, wallet.GetBalance(CurrencyType.PPoint)); // 100000 / 1000 = 100
}
[Fact]
public void Exchange_ShouldThrow_WhenSameCurrency()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
wallet.Deposit(100000m, CurrencyType.VND, "Deposit");
// Act & Assert
Assert.Throws<WalletDomainException>(() =>
wallet.Exchange(50000m, CurrencyType.VND, CurrencyType.VND));
}
[Fact]
public void Exchange_ShouldThrow_WhenInsufficientBalance()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
wallet.Deposit(50000m, CurrencyType.VND, "Deposit");
// Act & Assert
Assert.Throws<InsufficientBalanceException>(() =>
wallet.Exchange(100000m, CurrencyType.VND, CurrencyType.PPoint));
}
#endregion
#region Escrow Tests / Tests Quỹ
[Fact]
public void Hold_ShouldReduceAvailableBalanceAndCreateHoldItem()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
wallet.Deposit(1000m, CurrencyType.VND, "Init", "REF001");
// Act
var hold = wallet.Hold(100m, CurrencyType.VND, "REF", Guid.NewGuid(), "Desc");
// Assert
Assert.Equal(900m, wallet.GetBalance(CurrencyType.VND));
Assert.Single(wallet.Holds);
Assert.Equal(100m, wallet.GetTotalHeldAmount(CurrencyType.VND));
Assert.Equal(HoldStatus.Active, hold.Status);
}
[Fact]
public void Hold_ShouldThrow_WhenInsufficientBalance()
{
// Arrange
var wallet = new Wallet(TestUserId, CurrencyType.VND);
wallet.Deposit(50m, CurrencyType.VND, "Init", "REF001");
// Act & Assert
Assert.Throws<InsufficientBalanceException>(() =>
wallet.Hold(100m, CurrencyType.VND, "REF", Guid.NewGuid(), "Desc"));
}
#endregion
}