22using BuildingBlocks . TestBase ;
33using FluentAssertions ;
44using Integration . Test . Fakes ;
5+ using Microsoft . Extensions . Logging ;
56using Passenger . Data ;
67using Xunit ;
8+ using Xunit . Abstractions ;
79
810namespace Integration . Test . Passenger . Features ;
911
1012public class CompleteRegisterPassengerTests : PassengerIntegrationTestBase
1113{
12-
1314 public CompleteRegisterPassengerTests (
14- TestFixture < Program , PassengerDbContext , PassengerReadDbContext > integrationTestFactory ) : base ( integrationTestFactory )
15+ TestFixture < Program , PassengerDbContext , PassengerReadDbContext > integrationTestFactory ,
16+ ITestOutputHelper outputHelper
17+ )
18+ : base ( integrationTestFactory )
1519 {
20+ Fixture . Logger = Fixture . CreateLogger ( outputHelper ) ;
1621 }
1722
1823 [ Fact ]
1924 public async Task should_complete_register_passenger_and_update_to_db ( )
2025 {
2126 // Arrange
22- var userCreated = new FakeUserCreated ( ) . Generate ( ) ;
27+ Fixture . Logger ? . LogInformation ( "Starting CompleteRegisterPassenger test at {Time}" , DateTime . UtcNow ) ;
28+
29+ try
30+ {
31+ // Generate and publish UserCreated event
32+ var userCreated = new FakeUserCreated ( ) . Generate ( ) ;
33+ Fixture . Logger ? . LogInformation (
34+ "Generated UserCreated event with PassportNumber: {PassportNumber}" ,
35+ userCreated . PassportNumber
36+ ) ;
37+
38+ await Fixture . Publish ( userCreated ) ;
39+ Fixture . Logger ? . LogInformation ( "Published UserCreated event" ) ;
40+
41+ // Wait for publishing with retry logic
42+ var published = await WaitForWithRetry (
43+ async ( ) => await Fixture . WaitForPublishing < UserCreated > ( ) ,
44+ "publishing" ,
45+ maxRetries : 3
46+ ) ;
47+
48+ published . Should ( ) . BeTrue ( "UserCreated event should be published to message broker" ) ;
49+ Fixture . Logger ? . LogInformation ( "UserCreated event published successfully" ) ;
50+
51+ // Wait for consuming with retry logic
52+ var consumed = await WaitForWithRetry (
53+ async ( ) => await Fixture . WaitForConsuming < UserCreated > ( ) ,
54+ "consuming" ,
55+ maxRetries : 5
56+ ) ;
57+
58+ consumed . Should ( ) . BeTrue ( "UserCreated event should be consumed by the passenger service" ) ;
59+ Fixture . Logger ? . LogInformation ( "UserCreated event consumed successfully" ) ;
60+
61+ // Small delay to ensure event processing is complete
62+ await Task . Delay ( 1000 ) ;
63+
64+ // Generate and send complete registration command
65+ var command = new FakeCompleteRegisterPassengerCommand ( userCreated . PassportNumber ) . Generate ( ) ;
66+ Fixture . Logger ? . LogInformation (
67+ "Sending CompleteRegisterPassenger command for PassportNumber: {PassportNumber}" ,
68+ command . PassportNumber
69+ ) ;
70+
71+ // Act
72+ var response = await Fixture . SendAsync ( command ) ;
73+ Fixture . Logger ? . LogInformation ( "Received response for CompleteRegisterPassenger command" ) ;
74+
75+ // Assert with detailed logging
76+ response . Should ( ) . NotBeNull ( "Response should not be null" ) ;
77+ Fixture . Logger ? . LogInformation ( "Response is not null" ) ;
78+
79+ response ? . PassengerDto . Should ( ) . NotBeNull ( "PassengerDto should not be null" ) ;
80+
81+ response
82+ ? . PassengerDto ? . Name . Should ( )
83+ . Be (
84+ userCreated . Name ,
85+ $ "Passenger name should be '{ userCreated . Name } ' but was '{ response ? . PassengerDto ? . Name } '"
86+ ) ;
87+
88+ response
89+ ? . PassengerDto ? . PassportNumber . Should ( )
90+ . Be (
91+ command . PassportNumber ,
92+ $ "Passport number should be '{ command . PassportNumber } ' but was '{ response ? . PassengerDto ? . PassportNumber } '"
93+ ) ;
94+
95+ response
96+ ? . PassengerDto ? . PassengerType . ToString ( )
97+ . Should ( )
98+ . Be (
99+ command . PassengerType . ToString ( ) ,
100+ $ "Passenger type should be '{ command . PassengerType } ' but was '{ response ? . PassengerDto ? . PassengerType } '"
101+ ) ;
102+
103+ response
104+ ? . PassengerDto ? . Age . Should ( )
105+ . Be ( command . Age , $ "Age should be { command . Age } but was { response ? . PassengerDto ? . Age } ") ;
106+
107+ Fixture . Logger ? . LogInformation ( "All assertions passed successfully" ) ;
108+ }
109+ catch ( Exception ex )
110+ {
111+ Fixture . Logger ? . LogError ( ex , "Test failed with exception: {Message}" , ex . Message ) ;
112+ throw ;
113+ }
114+ finally
115+ {
116+ Fixture . Logger ? . LogInformation ( "Test completed at {Time}" , DateTime . UtcNow ) ;
117+ }
118+ }
119+
120+ private async Task < bool > WaitForWithRetry ( Func < Task < bool > > waitCondition , string operation , int maxRetries = 3 )
121+ {
122+ for ( int i = 0 ; i < maxRetries ; i ++ )
123+ {
124+ Fixture . Logger ? . LogInformation (
125+ "Attempt {Attempt}/{MaxRetries} for {Operation}" ,
126+ i + 1 ,
127+ maxRetries ,
128+ operation
129+ ) ;
23130
24- await Fixture . Publish ( userCreated ) ;
25- ( await Fixture . WaitForPublishing < UserCreated > ( ) ) . Should ( ) . Be ( true ) ;
26- ( await Fixture . WaitForConsuming < UserCreated > ( ) ) . Should ( ) . Be ( true ) ;
131+ var result = await waitCondition ( ) ;
27132
28- var command = new FakeCompleteRegisterPassengerCommand ( userCreated . PassportNumber ) . Generate ( ) ;
133+ if ( result )
134+ {
135+ Fixture . Logger ? . LogInformation ( "{Operation} successful on attempt {Attempt}" , operation , i + 1 ) ;
136+ return true ;
137+ }
29138
30- // Act
31- var response = await Fixture . SendAsync ( command ) ;
139+ if ( i < maxRetries - 1 )
140+ {
141+ var delaySeconds = ( i + 1 ) * 2 ; // Exponential backoff: 2, 4, 6 seconds
142+ Fixture . Logger ? . LogWarning (
143+ "{Operation} failed on attempt {Attempt}, waiting {Delay}s before retry" ,
144+ operation ,
145+ i + 1 ,
146+ delaySeconds
147+ ) ;
148+ await Task . Delay ( TimeSpan . FromSeconds ( delaySeconds ) ) ;
149+ }
150+ }
32151
33- // Assert
34- response . Should ( ) . NotBeNull ( ) ;
35- response ? . PassengerDto ? . Name . Should ( ) . Be ( userCreated . Name ) ;
36- response ? . PassengerDto ? . PassportNumber . Should ( ) . Be ( command . PassportNumber ) ;
37- response ? . PassengerDto ? . PassengerType . ToString ( ) . Should ( ) . Be ( command . PassengerType . ToString ( ) ) ;
38- response ? . PassengerDto ? . Age . Should ( ) . Be ( command . Age ) ;
152+ Fixture . Logger ? . LogError ( "{Operation} failed after {MaxRetries} attempts" , operation , maxRetries ) ;
153+ return false ;
39154 }
40- }
155+ }
0 commit comments