1+ using FluentAssertions ;
2+ using Microsoft . EntityFrameworkCore ;
3+ using Microsoft . Extensions . Logging ;
4+ using Moq ;
5+ using ProjectVG . Application . Services . Credit ;
6+ using ProjectVG . Domain . Entities . Credits ;
7+ using ProjectVG . Domain . Entities . Users ;
8+ using ProjectVG . Domain . Repositories ;
9+ using ProjectVG . Infrastructure . Persistence . EfCore ;
10+ using ProjectVG . Infrastructure . Persistence . Repositories . Credit ;
11+ using ProjectVG . Infrastructure . Persistence . Repositories . Users ;
12+ using Xunit ;
13+
14+ namespace ProjectVG . Tests . Application . Services . Credit
15+ {
16+ public class CreditManagementServiceTests : IDisposable
17+ {
18+ private readonly ProjectVGDbContext _context ;
19+ private readonly IUserRepository _userRepository ;
20+ private readonly ICreditTransactionRepository _transactionRepository ;
21+ private readonly Mock < ILogger < CreditManagementService > > _mockLogger ;
22+ private readonly CreditManagementService _service ;
23+
24+ public CreditManagementServiceTests ( )
25+ {
26+ // Create in-memory database
27+ var options = new DbContextOptionsBuilder < ProjectVGDbContext > ( )
28+ . UseInMemoryDatabase ( databaseName : Guid . NewGuid ( ) . ToString ( ) )
29+ . Options ;
30+
31+ _context = new ProjectVGDbContext ( options ) ;
32+ _userRepository = new SqlServerUserRepository ( _context , new Mock < ILogger < SqlServerUserRepository > > ( ) . Object ) ;
33+ _transactionRepository = new SqlServerCreditTransactionRepository ( _context , new Mock < ILogger < SqlServerCreditTransactionRepository > > ( ) . Object ) ;
34+ _mockLogger = new Mock < ILogger < CreditManagementService > > ( ) ;
35+
36+ _service = new CreditManagementService (
37+ _context ,
38+ _userRepository ,
39+ _transactionRepository ,
40+ _mockLogger . Object
41+ ) ;
42+ }
43+
44+ [ Fact ]
45+ public async Task GetCreditBalanceAsync_WithValidUser_ShouldReturnCreditBalance ( )
46+ {
47+ // Arrange
48+ var user = new ProjectVG . Domain . Entities . Users . User
49+ {
50+ Id = Guid . NewGuid ( ) ,
51+ UID = "TEST12345" ,
52+ ProviderId = "test-provider-id" ,
53+ Provider = "test" ,
54+ Email = "test@example.com" ,
55+ Username = "testuser" ,
56+ CreditBalance = 500.50m ,
57+ TotalCreditsEarned = 1000m ,
58+ TotalCreditsSpent = 499.50m
59+ } ;
60+
61+ _context . Users . Add ( user ) ;
62+ await _context . SaveChangesAsync ( ) ;
63+
64+ // Act
65+ var result = await _service . GetCreditBalanceAsync ( user . Id ) ;
66+
67+ // Assert
68+ result . Should ( ) . NotBeNull ( ) ;
69+ result . UserId . Should ( ) . Be ( user . Id ) ;
70+ result . CurrentBalance . Should ( ) . Be ( 500.50m ) ;
71+ result . TotalEarned . Should ( ) . Be ( 1000m ) ;
72+ result . TotalSpent . Should ( ) . Be ( 499.50m ) ;
73+ }
74+
75+ [ Fact ]
76+ public async Task HasSufficientCreditsAsync_WithSufficientBalance_ShouldReturnTrue ( )
77+ {
78+ // Arrange
79+ var user = new ProjectVG . Domain . Entities . Users . User
80+ {
81+ Id = Guid . NewGuid ( ) ,
82+ UID = "TEST12346" ,
83+ ProviderId = "test-provider-id-2" ,
84+ Provider = "test" ,
85+ Email = "test2@example.com" ,
86+ Username = "testuser2" ,
87+ CreditBalance = 100m
88+ } ;
89+
90+ _context . Users . Add ( user ) ;
91+ await _context . SaveChangesAsync ( ) ;
92+
93+ // Act
94+ var result = await _service . HasSufficientCreditsAsync ( user . Id , 50m ) ;
95+
96+ // Assert
97+ result . Should ( ) . BeTrue ( ) ;
98+ }
99+
100+ [ Fact ]
101+ public async Task HasSufficientCreditsAsync_WithInsufficientBalance_ShouldReturnFalse ( )
102+ {
103+ // Arrange
104+ var user = new ProjectVG . Domain . Entities . Users . User
105+ {
106+ Id = Guid . NewGuid ( ) ,
107+ UID = "TEST12347" ,
108+ ProviderId = "test-provider-id-3" ,
109+ Provider = "test" ,
110+ Email = "test3@example.com" ,
111+ Username = "testuser3" ,
112+ CreditBalance = 30m
113+ } ;
114+
115+ _context . Users . Add ( user ) ;
116+ await _context . SaveChangesAsync ( ) ;
117+
118+ // Act
119+ var result = await _service . HasSufficientCreditsAsync ( user . Id , 50m ) ;
120+
121+ // Assert
122+ result . Should ( ) . BeFalse ( ) ;
123+ }
124+
125+ [ Fact ]
126+ public async Task GetCreditHistoryAsync_WithValidUser_ShouldReturnHistory ( )
127+ {
128+ // Arrange
129+ var user = new ProjectVG . Domain . Entities . Users . User
130+ {
131+ Id = Guid . NewGuid ( ) ,
132+ UID = "TEST12348" ,
133+ ProviderId = "test-provider-id-4" ,
134+ Provider = "test" ,
135+ Email = "test4@example.com" ,
136+ Username = "testuser4" ,
137+ CreditBalance = 100m
138+ } ;
139+
140+ var transaction = new CreditTransaction
141+ {
142+ UserId = user . Id ,
143+ TransactionId = "TXN-TEST-001" ,
144+ Type = CreditTransactionType . Earn ,
145+ Amount = 100m ,
146+ BalanceAfter = 100m ,
147+ Source = "TEST" ,
148+ Description = "Test transaction"
149+ } ;
150+
151+ _context . Users . Add ( user ) ;
152+ _context . CreditTransactions . Add ( transaction ) ;
153+ await _context . SaveChangesAsync ( ) ;
154+
155+ // Act
156+ var result = await _service . GetCreditHistoryAsync ( user . Id , 1 , 10 ) ;
157+
158+ // Assert
159+ result . Should ( ) . NotBeNull ( ) ;
160+ result . UserId . Should ( ) . Be ( user . Id ) ;
161+ result . Transactions . Should ( ) . HaveCount ( 1 ) ;
162+ result . TotalCount . Should ( ) . Be ( 1 ) ;
163+ result . PageNumber . Should ( ) . Be ( 1 ) ;
164+ result . PageSize . Should ( ) . Be ( 10 ) ;
165+ result . Transactions . First ( ) . Amount . Should ( ) . Be ( 100m ) ;
166+ }
167+
168+ public void Dispose ( )
169+ {
170+ _context . Dispose ( ) ;
171+ }
172+ }
173+ }
0 commit comments