Merge branch 'fix/fix-ci-failed'

This commit is contained in:
Meysam Hadeli 2026-02-20 00:27:53 +03:30
commit 3ce312891a
4 changed files with 25 additions and 155 deletions

View File

@ -19,6 +19,12 @@
"commands": [
"aspire"
]
},
"csharpier": {
"version": "0.30.6",
"commands": [
"dotnet-csharpier"
]
}
}
}

View File

@ -7,8 +7,8 @@
"main": "index.js",
"scripts": {
"prepare": "husky && dotnet tool restore",
"format": "dotnet format booking-microservices.sln --severity error --verbosity detailed",
"ci-format": "dotnet format booking-microservices.sln --verify-no-changes --severity error --verbosity detailed",
"format": "dotnet tool run dotnet-csharpier booking-microservices.sln",
"ci-format": "dotnet tool run dotnet-csharpier booking-microservices.sln --check",
"upgrade-packages": "dotnet outdated --upgrade"
},
"devDependencies": {

View File

@ -136,23 +136,10 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
{
CancellationTokenSource = new CancellationTokenSource();
await StartTestContainerAsync();
if (ServiceProvider.GetService<ITestHarness>() is { } harness)
{
await harness.Start();
// Add a small delay to ensure harness is ready
await Task.Delay(1000);
}
}
public async Task DisposeAsync()
{
if (ServiceProvider.GetService<ITestHarness>() is { } harness)
{
await harness.Stop();
}
await StopTestContainerAsync();
await _factory.DisposeAsync();
await CancellationTokenSource.CancelAsync();
@ -312,13 +299,6 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
// Start RabbitMQ last and wait extra time
await RabbitMqTestContainer.StartAsync();
await Task.Delay(5000); // Give RabbitMQ extra time to initialize
// Verify RabbitMQ is healthy
var healthCheck = await RabbitMqTestContainer.ExecAsync(new[] { "rabbitmq-diagnostics", "ping" });
if (healthCheck.ExitCode != 0)
{
await Task.Delay(5000); // Wait more if not healthy
}
}
private async Task StopTestContainerAsync()

View File

@ -2,154 +2,38 @@ using BuildingBlocks.Contracts.EventBus.Messages;
using BuildingBlocks.TestBase;
using FluentAssertions;
using Integration.Test.Fakes;
using Microsoft.Extensions.Logging;
using Passenger.Data;
using Xunit;
using Xunit.Abstractions;
namespace Integration.Test.Passenger.Features;
public class CompleteRegisterPassengerTests : PassengerIntegrationTestBase
{
public CompleteRegisterPassengerTests(
TestFixture<Program, PassengerDbContext, PassengerReadDbContext> integrationTestFactory,
ITestOutputHelper outputHelper
TestFixture<Program, PassengerDbContext, PassengerReadDbContext> integrationTestFactory
)
: base(integrationTestFactory)
{
Fixture.Logger = Fixture.CreateLogger(outputHelper);
}
: base(integrationTestFactory) { }
[Fact]
public async Task should_complete_register_passenger_and_update_to_db()
{
// Arrange
Fixture.Logger?.LogInformation("Starting CompleteRegisterPassenger test at {Time}", DateTime.UtcNow);
var userCreated = new FakeUserCreated().Generate();
try
{
// Generate and publish UserCreated event
var userCreated = new FakeUserCreated().Generate();
Fixture.Logger?.LogInformation(
"Generated UserCreated event with PassportNumber: {PassportNumber}",
userCreated.PassportNumber
);
await Fixture.Publish(userCreated);
(await Fixture.WaitForPublishing<UserCreated>()).Should().Be(true);
(await Fixture.WaitForConsuming<UserCreated>()).Should().Be(true);
await Fixture.Publish(userCreated);
Fixture.Logger?.LogInformation("Published UserCreated event");
var command = new FakeCompleteRegisterPassengerCommand(userCreated.PassportNumber).Generate();
// Wait for publishing with retry logic
var published = await WaitForWithRetry(
async () => await Fixture.WaitForPublishing<UserCreated>(),
"publishing",
maxRetries: 3
);
// Act
var response = await Fixture.SendAsync(command);
published.Should().BeTrue("UserCreated event should be published to message broker");
Fixture.Logger?.LogInformation("UserCreated event published successfully");
// Wait for consuming with retry logic
var consumed = await WaitForWithRetry(
async () => await Fixture.WaitForConsuming<UserCreated>(),
"consuming",
maxRetries: 5
);
consumed.Should().BeTrue("UserCreated event should be consumed by the passenger service");
Fixture.Logger?.LogInformation("UserCreated event consumed successfully");
// Small delay to ensure event processing is complete
await Task.Delay(1000);
// Generate and send complete registration command
var command = new FakeCompleteRegisterPassengerCommand(userCreated.PassportNumber).Generate();
Fixture.Logger?.LogInformation(
"Sending CompleteRegisterPassenger command for PassportNumber: {PassportNumber}",
command.PassportNumber
);
// Act
var response = await Fixture.SendAsync(command);
Fixture.Logger?.LogInformation("Received response for CompleteRegisterPassenger command");
// Assert with detailed logging
response.Should().NotBeNull("Response should not be null");
Fixture.Logger?.LogInformation("Response is not null");
response?.PassengerDto.Should().NotBeNull("PassengerDto should not be null");
response
?.PassengerDto?.Name.Should()
.Be(
userCreated.Name,
$"Passenger name should be '{userCreated.Name}' but was '{response?.PassengerDto?.Name}'"
);
response
?.PassengerDto?.PassportNumber.Should()
.Be(
command.PassportNumber,
$"Passport number should be '{command.PassportNumber}' but was '{response?.PassengerDto?.PassportNumber}'"
);
response
?.PassengerDto?.PassengerType.ToString()
.Should()
.Be(
command.PassengerType.ToString(),
$"Passenger type should be '{command.PassengerType}' but was '{response?.PassengerDto?.PassengerType}'"
);
response
?.PassengerDto?.Age.Should()
.Be(command.Age, $"Age should be {command.Age} but was {response?.PassengerDto?.Age}");
Fixture.Logger?.LogInformation("All assertions passed successfully");
}
catch (Exception ex)
{
Fixture.Logger?.LogError(ex, "Test failed with exception: {Message}", ex.Message);
throw;
}
finally
{
Fixture.Logger?.LogInformation("Test completed at {Time}", DateTime.UtcNow);
}
}
private async Task<bool> WaitForWithRetry(Func<Task<bool>> waitCondition, string operation, int maxRetries = 3)
{
for (int i = 0; i < maxRetries; i++)
{
Fixture.Logger?.LogInformation(
"Attempt {Attempt}/{MaxRetries} for {Operation}",
i + 1,
maxRetries,
operation
);
var result = await waitCondition();
if (result)
{
Fixture.Logger?.LogInformation("{Operation} successful on attempt {Attempt}", operation, i + 1);
return true;
}
if (i < maxRetries - 1)
{
var delaySeconds = (i + 1) * 2; // Exponential backoff: 2, 4, 6 seconds
Fixture.Logger?.LogWarning(
"{Operation} failed on attempt {Attempt}, waiting {Delay}s before retry",
operation,
i + 1,
delaySeconds
);
await Task.Delay(TimeSpan.FromSeconds(delaySeconds));
}
}
Fixture.Logger?.LogError("{Operation} failed after {MaxRetries} attempts", operation, maxRetries);
return false;
// Assert
response.Should().NotBeNull();
response?.PassengerDto?.Name.Should().Be(userCreated.Name);
response?.PassengerDto?.PassportNumber.Should().Be(command.PassportNumber);
response?.PassengerDto?.PassengerType.ToString().Should().Be(command.PassengerType.ToString());
response?.PassengerDto?.Age.Should().Be(command.Age);
}
}