Merge pull request #370 from meysamhadeli/fix/fix-ci-failed

fix: fix ci failed
This commit is contained in:
Meysam Hadeli 2026-02-19 23:19:09 +03:30 committed by GitHub
commit 786fbb121f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 158 additions and 36 deletions

View File

@ -42,7 +42,7 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
where TEntryPoint : class
{
private readonly WebApplicationFactory<TEntryPoint> _factory;
private int Timeout => 120; // Second
private int Timeout => 300; // Second
private ITestHarness TestHarness => ServiceProvider?.GetTestHarness();
private Action<IServiceCollection> TestRegistrationServices { get; set; }
private PostgreSqlContainer PostgresTestcontainer;
@ -140,6 +140,9 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
if (ServiceProvider.GetService<ITestHarness>() is { } harness)
{
await harness.Start();
// Add a small delay to ensure harness is ready
await Task.Delay(1000);
}
}
@ -298,11 +301,24 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
MongoDbTestContainer = TestContainers.MongoTestContainer();
EventStoreDbTestContainer = TestContainers.EventStoreTestContainer();
await MongoDbTestContainer.StartAsync();
await PostgresTestcontainer.StartAsync();
await PostgresPersistTestContainer.StartAsync();
// Start containers in parallel for speed
await Task.WhenAll(
MongoDbTestContainer.StartAsync(),
PostgresTestcontainer.StartAsync(),
PostgresPersistTestContainer.StartAsync(),
EventStoreDbTestContainer.StartAsync()
);
// Start RabbitMQ last and wait extra time
await RabbitMqTestContainer.StartAsync();
await EventStoreDbTestContainer.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()
@ -727,4 +743,4 @@ public abstract class TestBase<TEntryPoint, TWContext, TRContext> : TestFixtureC
}
public TestFixture<TEntryPoint, TWContext, TRContext> Fixture { get; }
}
}

View File

@ -87,25 +87,16 @@ public static class TestContainers
public static RabbitMqContainer RabbitMqTestContainer()
{
var builder = new RabbitMqBuilder()
var baseBuilder = new RabbitMqBuilder()
.WithUsername(RabbitMqContainerConfiguration.UserName)
.WithPassword(RabbitMqContainerConfiguration.Password)
.WithLabel("Key", "Value");
var builder = baseBuilder
.WithImage(RabbitMqContainerConfiguration.ImageName)
.WithName(RabbitMqContainerConfiguration.Name)
.WithPortBinding(RabbitMqContainerConfiguration.ApiPort, true)
.WithPortBinding(RabbitMqContainerConfiguration.Port, true)
.WithWaitStrategy(
Wait.ForUnixContainer()
.UntilHttpRequestIsSucceeded(request =>
request
.ForPort((ushort)RabbitMqContainerConfiguration.ApiPort)
.ForPath("/api/overview")
.WithBasicAuthentication(
RabbitMqContainerConfiguration.UserName,
RabbitMqContainerConfiguration.Password
)
)
)
.Build();
return builder;
@ -166,4 +157,4 @@ public static class TestContainers
public int Port { get; set; } = 2113;
public string ImageName { get; set; } = "eventstore/eventstore:latest";
}
}
}

View File

@ -2,39 +2,154 @@ 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) : base(integrationTestFactory)
TestFixture<Program, PassengerDbContext, PassengerReadDbContext> integrationTestFactory,
ITestOutputHelper outputHelper
)
: base(integrationTestFactory)
{
Fixture.Logger = Fixture.CreateLogger(outputHelper);
}
[Fact]
public async Task should_complete_register_passenger_and_update_to_db()
{
// Arrange
var userCreated = new FakeUserCreated().Generate();
Fixture.Logger?.LogInformation("Starting CompleteRegisterPassenger test at {Time}", DateTime.UtcNow);
await Fixture.Publish(userCreated);
(await Fixture.WaitForPublishing<UserCreated>()).Should().Be(true);
(await Fixture.WaitForConsuming<UserCreated>()).Should().Be(true);
try
{
// Generate and publish UserCreated event
var userCreated = new FakeUserCreated().Generate();
Fixture.Logger?.LogInformation(
"Generated UserCreated event with PassportNumber: {PassportNumber}",
userCreated.PassportNumber
);
var command = new FakeCompleteRegisterPassengerCommand(userCreated.PassportNumber).Generate();
await Fixture.Publish(userCreated);
Fixture.Logger?.LogInformation("Published UserCreated event");
// Act
var response = await Fixture.SendAsync(command);
// Wait for publishing with retry logic
var published = await WaitForWithRetry(
async () => await Fixture.WaitForPublishing<UserCreated>(),
"publishing",
maxRetries: 3
);
// 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);
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;
}
}