From db0da365b0c583ede7c39de921968ea32ca4f243 Mon Sep 17 00:00:00 2001 From: Pc Date: Sat, 11 Mar 2023 19:15:50 +0330 Subject: [PATCH] test: Update test-container to v3.0.0 for support event-store --- src/BuildingBlocks/BuildingBlocks.csproj | 6 +- src/BuildingBlocks/CAP/Extensions.cs | 2 +- .../PersistMessageProcessor/Extensions.cs | 40 ++++ src/BuildingBlocks/TestBase/TestBase.cs | 63 +++--- src/BuildingBlocks/TestBase/TestContainers.cs | 189 +++++++++++++----- .../InfrastructureExtensions.cs | 4 +- .../Booking/Features/CreateBookingTests.cs | 138 ++++++------- 7 files changed, 291 insertions(+), 151 deletions(-) diff --git a/src/BuildingBlocks/BuildingBlocks.csproj b/src/BuildingBlocks/BuildingBlocks.csproj index d55c810..1fc9ba9 100644 --- a/src/BuildingBlocks/BuildingBlocks.csproj +++ b/src/BuildingBlocks/BuildingBlocks.csproj @@ -101,7 +101,11 @@ - + + + + + diff --git a/src/BuildingBlocks/CAP/Extensions.cs b/src/BuildingBlocks/CAP/Extensions.cs index db8c03f..f0a2a90 100644 --- a/src/BuildingBlocks/CAP/Extensions.cs +++ b/src/BuildingBlocks/CAP/Extensions.cs @@ -15,7 +15,7 @@ public static class Extensions public static IServiceCollection AddCustomCap(this IServiceCollection services) where TDbContext : DbContext { - var rabbitMqOptions = services.GetOptions("RabbitMq"); + var rabbitMqOptions = services.GetOptions(nameof(RabbitMQOptions)); services.AddCap(x => { diff --git a/src/BuildingBlocks/PersistMessageProcessor/Extensions.cs b/src/BuildingBlocks/PersistMessageProcessor/Extensions.cs index eb52849..444a0ca 100644 --- a/src/BuildingBlocks/PersistMessageProcessor/Extensions.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/Extensions.cs @@ -5,6 +5,11 @@ using Microsoft.Extensions.DependencyInjection; namespace BuildingBlocks.PersistMessageProcessor; +using EFCore; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; + public static class Extensions { public static IServiceCollection AddPersistMessageProcessor(this IServiceCollection services) @@ -33,4 +38,39 @@ public static class Extensions return services; } + + public static IApplicationBuilder UseMigration(this IApplicationBuilder app, IWebHostEnvironment env) + where TContext : DbContext, IPersistMessageDbContext + { + MigrateDatabaseAsync(app.ApplicationServices).GetAwaiter().GetResult(); + + if (!env.IsEnvironment("test")) + { + SeedDataAsync(app.ApplicationServices).GetAwaiter().GetResult(); + } + + return app; + } + + private static async Task MigrateDatabaseAsync(IServiceProvider serviceProvider) + where TContext : DbContext, IPersistMessageDbContext + { + using var scope = serviceProvider.CreateScope(); + + var persistMessageContext = scope.ServiceProvider.GetRequiredService(); + await persistMessageContext.Database.MigrateAsync(); + + var context = scope.ServiceProvider.GetRequiredService(); + await context.Database.MigrateAsync(); + } + + private static async Task SeedDataAsync(IServiceProvider serviceProvider) + { + using var scope = serviceProvider.CreateScope(); + var seeders = scope.ServiceProvider.GetServices(); + foreach (var seeder in seeders) + { + await seeder.SeedAllAsync(); + } + } } diff --git a/src/BuildingBlocks/TestBase/TestBase.cs b/src/BuildingBlocks/TestBase/TestBase.cs index 23429cc..7fcd694 100644 --- a/src/BuildingBlocks/TestBase/TestBase.cs +++ b/src/BuildingBlocks/TestBase/TestBase.cs @@ -30,8 +30,12 @@ using WebMotions.Fake.Authentication.JwtBearer; namespace BuildingBlocks.TestBase; +using System.Globalization; using Npgsql; -using Exception = System.Exception; +using Testcontainers.EventStoreDb; +using Testcontainers.MongoDb; +using Testcontainers.PostgreSql; +using Testcontainers.RabbitMq; public class TestFixture : IAsyncLifetime where TEntryPoint : class @@ -40,10 +44,11 @@ public class TestFixture : IAsyncLifetime private int Timeout => 120; // Second private ITestHarness TestHarness => ServiceProvider?.GetTestHarness(); private Action TestRegistrationServices { get; set; } - private PostgreSqlTestcontainer PostgresTestcontainer; - private PostgreSqlTestcontainer PostgresPersistTestContainer; - public RabbitMqTestcontainer RabbitMqTestContainer; - public MongoDbTestcontainer MongoDbTestContainer; + private PostgreSqlContainer PostgresTestcontainer; + private PostgreSqlContainer PostgresPersistTestContainer; + public RabbitMqContainer RabbitMqTestContainer; + public MongoDbContainer MongoDbTestContainer; + public EventStoreDbContainer EventStoreDbTestContainer; public HttpClient HttpClient { @@ -151,7 +156,6 @@ public class TestFixture : IAsyncLifetime return ExecuteScopeAsync(sp => { var mediator = sp.GetRequiredService(); - return mediator.Send(request); }); } @@ -238,15 +242,17 @@ public class TestFixture : IAsyncLifetime private async Task StartTestContainerAsync() { - PostgresTestcontainer = TestContainers.PostgresTestContainer; - PostgresPersistTestContainer = TestContainers.PostgresPersistTestContainer; - RabbitMqTestContainer = TestContainers.RabbitMqTestContainer; - MongoDbTestContainer = TestContainers.MongoTestContainer; + PostgresTestcontainer = TestContainers.PostgresTestContainer(); + PostgresPersistTestContainer = TestContainers.PostgresPersistTestContainer(); + RabbitMqTestContainer = TestContainers.RabbitMqTestContainer(); + MongoDbTestContainer = TestContainers.MongoTestContainer(); + EventStoreDbTestContainer = TestContainers.EventStoreTestContainer(); await MongoDbTestContainer.StartAsync(); await PostgresTestcontainer.StartAsync(); await PostgresPersistTestContainer.StartAsync(); await RabbitMqTestContainer.StartAsync(); + await EventStoreDbTestContainer.StartAsync(); } private async Task StopTestContainerAsync() @@ -255,20 +261,24 @@ public class TestFixture : IAsyncLifetime await PostgresPersistTestContainer.StopAsync(); await RabbitMqTestContainer.StopAsync(); await MongoDbTestContainer.StopAsync(); + await EventStoreDbTestContainer.StopAsync(); } private void AddCustomAppSettings(IConfigurationBuilder configuration) { configuration.AddInMemoryCollection(new KeyValuePair[] { - new("PostgresOptions:ConnectionString", PostgresTestcontainer.ConnectionString), - new("PersistMessageOptions:ConnectionString", PostgresPersistTestContainer.ConnectionString), + new("PostgresOptions:ConnectionString", PostgresTestcontainer.GetConnectionString()), + new("PersistMessageOptions:ConnectionString", PostgresPersistTestContainer.GetConnectionString()), new("RabbitMqOptions:HostName", RabbitMqTestContainer.Hostname), - new("RabbitMqOptions:UserName", RabbitMqTestContainer.Username), - new("RabbitMqOptions:Password", RabbitMqTestContainer.Password), - new("RabbitMqOptions:Port", RabbitMqTestContainer.Port.ToString()), - new("MongoOptions:ConnectionString", MongoDbTestContainer.ConnectionString), - new("MongoOptions:DatabaseName", MongoDbTestContainer.Database) + new("RabbitMqOptions:UserName", TestContainers.RabbitMqContainerConfiguration.UserName), + new("RabbitMqOptions:Password", TestContainers.RabbitMqContainerConfiguration.Password), new( + "RabbitMqOptions:Port", + RabbitMqTestContainer.GetMappedPublicPort(TestContainers.RabbitMqContainerConfiguration.Port) + .ToString(NumberFormatInfo.InvariantInfo)), + new("MongoOptions:ConnectionString", MongoDbTestContainer.GetConnectionString()), + new("MongoOptions:DatabaseName", TestContainers.MongoContainerConfiguration.Name), + new("EventStore:ConnectionString", EventStoreDbTestContainer.GetConnectionString()) }); } @@ -450,6 +460,7 @@ public class TestFixtureCore : IAsyncLifetime private NpgsqlConnection DefaultDbConnection { get; set; } private NpgsqlConnection PersistDbConnection { get; set; } + public TestFixtureCore(TestFixture integrationTestFixture, ITestOutputHelper outputHelper) { Fixture = integrationTestFixture; @@ -474,8 +485,8 @@ public class TestFixtureCore : IAsyncLifetime private async Task InitPostgresAsync() { - var postgresOptions = Fixture.ServiceProvider.GetRequiredService(); - var persistOptions = Fixture.ServiceProvider.GetRequiredService(); + var postgresOptions = Fixture.ServiceProvider.GetService(); + var persistOptions = Fixture.ServiceProvider.GetService(); if (!string.IsNullOrEmpty(persistOptions?.ConnectionString)) { @@ -514,24 +525,26 @@ public class TestFixtureCore : IAsyncLifetime private async Task ResetMongoAsync(CancellationToken cancellationToken = default) { //https://stackoverflow.com/questions/3366397/delete-everything-in-a-mongodb-database - var dbClient = new MongoClient(Fixture.MongoDbTestContainer?.ConnectionString); - var collections = await dbClient.GetDatabase(Fixture.MongoDbTestContainer?.Database) + var dbClient = new MongoClient(Fixture.MongoDbTestContainer?.GetConnectionString()); + var collections = await dbClient.GetDatabase(TestContainers.MongoContainerConfiguration.Name) .ListCollectionsAsync(cancellationToken: cancellationToken); foreach (var collection in collections.ToList()) { - await dbClient.GetDatabase(Fixture.MongoDbTestContainer?.Database) + await dbClient.GetDatabase(TestContainers.MongoContainerConfiguration.Name) .DropCollectionAsync(collection["name"].AsString, cancellationToken); } } private async Task ResetRabbitMqAsync(CancellationToken cancellationToken = default) { - var port = Fixture.RabbitMqTestContainer?.GetMappedPublicPort(15672) ?? 15672; + var port = Fixture.RabbitMqTestContainer?.GetMappedPublicPort(TestContainers.RabbitMqContainerConfiguration + .ApiPort) + ?? TestContainers.RabbitMqContainerConfiguration.ApiPort; var managementClient = new ManagementClient(Fixture.RabbitMqTestContainer?.Hostname, - Fixture.RabbitMqTestContainer?.Username, - Fixture.RabbitMqTestContainer?.Password, port); + TestContainers.RabbitMqContainerConfiguration?.UserName, + TestContainers.RabbitMqContainerConfiguration?.Password, port); var bd = await managementClient.GetBindingsAsync(cancellationToken); var bindings = bd.Where(x => !string.IsNullOrEmpty(x.Source) && !string.IsNullOrEmpty(x.Destination)); diff --git a/src/BuildingBlocks/TestBase/TestContainers.cs b/src/BuildingBlocks/TestBase/TestContainers.cs index e862091..c7ef2dd 100644 --- a/src/BuildingBlocks/TestBase/TestContainers.cs +++ b/src/BuildingBlocks/TestBase/TestContainers.cs @@ -1,62 +1,149 @@ -using System; -using DotNet.Testcontainers.Builders; -using DotNet.Testcontainers.Configurations; -using DotNet.Testcontainers.Containers; - -namespace BuildingBlocks.TestBase; +namespace BuildingBlocks.TestBase; +using Testcontainers.EventStoreDb; +using Testcontainers.MongoDb; +using Testcontainers.PostgreSql; +using Testcontainers.RabbitMq; +using Web; public static class TestContainers { - public static PostgreSqlTestcontainer PostgresTestContainer => new TestcontainersBuilder() - .WithDatabase( - new PostgreSqlTestcontainerConfiguration - { - Database = Guid.NewGuid().ToString("D"), - Password = Guid.NewGuid().ToString("D"), - Username = Guid.NewGuid().ToString("D") - }) - .WithImage("postgres:latest") - .WithPortBinding(5432, true) - .WithCleanUp(true) - .Build(); + public static RabbitMqContainerOptions RabbitMqContainerConfiguration { get;} + public static PostgresContainerOptions PostgresContainerConfiguration { get;} + public static PostgresPersistContainerOptions PostgresPersistContainerConfiguration { get;} + public static MongoContainerOptions MongoContainerConfiguration { get;} + public static EventStoreContainerOptions EventStoreContainerConfiguration { get;} - public static PostgreSqlTestcontainer PostgresPersistTestContainer => new TestcontainersBuilder() - .WithDatabase( - new PostgreSqlTestcontainerConfiguration - { - Database = Guid.NewGuid().ToString("D"), - Password = Guid.NewGuid().ToString("D"), - Username = Guid.NewGuid().ToString("D") - }) - .WithImage("postgres:latest") - .WithPortBinding(5432, true) - .WithCleanUp(true) - .Build(); + static TestContainers() + { + var configuration = ConfigurationHelper.GetConfiguration(); + RabbitMqContainerConfiguration = configuration.GetOptions(nameof(RabbitMqContainerOptions)); + PostgresContainerConfiguration = configuration.GetOptions(nameof(PostgresContainerOptions)); + PostgresPersistContainerConfiguration = configuration.GetOptions(nameof(PostgresPersistContainerOptions)); + MongoContainerConfiguration = configuration.GetOptions(nameof(MongoContainerOptions)); + EventStoreContainerConfiguration = configuration.GetOptions(nameof(EventStoreContainerOptions)); + } - public static MongoDbTestcontainer MongoTestContainer => new TestcontainersBuilder() - .WithDatabase(new MongoDbTestcontainerConfiguration() - { - Database = Guid.NewGuid().ToString("D"), - Username = Guid.NewGuid().ToString("D"), - Password = Guid.NewGuid().ToString("D"), - }) - .WithImage("mongo:5") - .WithCleanUp(true) - .Build(); + public static PostgreSqlContainer PostgresTestContainer() + { + var baseBuilder = new PostgreSqlBuilder() + .WithUsername(PostgresContainerConfiguration.UserName) + .WithPassword(PostgresContainerConfiguration.Password) + .WithLabel("Key", "Value"); + var builder = baseBuilder + .WithImage(PostgresContainerConfiguration.ImageName) + .WithName(PostgresContainerConfiguration.Name) + .WithPortBinding(PostgresContainerConfiguration.Port, true) + .Build(); - public static RabbitMqTestcontainer RabbitMqTestContainer => new TestcontainersBuilder() - .WithMessageBroker(new RabbitMqTestcontainerConfiguration() - { - Password = "guest", - Username = "guest" - }) - .WithImage("rabbitmq:3-management") - .WithPortBinding(15672, true) - .WithPortBinding(5672, true) - .WithCleanUp(true) - .Build(); + return builder; + } + public static PostgreSqlContainer PostgresPersistTestContainer() + { + var baseBuilder = new PostgreSqlBuilder() + .WithUsername(PostgresPersistContainerConfiguration.UserName) + .WithPassword(PostgresPersistContainerConfiguration.Password) + .WithLabel("Key", "Value"); + var builder = baseBuilder + .WithImage(PostgresPersistContainerConfiguration.ImageName) + .WithName(PostgresPersistContainerConfiguration.Name) + .WithPortBinding(PostgresPersistContainerConfiguration.Port, true) + .Build(); + + return builder; + } + + public static MongoDbContainer MongoTestContainer() + { + var baseBuilder = new MongoDbBuilder() + .WithUsername(MongoContainerConfiguration.UserName) + .WithPassword(MongoContainerConfiguration.Password) + .WithLabel("Key", "Value"); + + var builder = baseBuilder + .WithImage(MongoContainerConfiguration.ImageName) + .WithName(MongoContainerConfiguration.Name) + .WithPortBinding(MongoContainerConfiguration.Port, true) + .Build(); + + return builder; + } + + public static RabbitMqContainer RabbitMqTestContainer() + { + 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) + .Build(); + + return builder; + } + + public static EventStoreDbContainer EventStoreTestContainer() + { + var baseBuilder = new EventStoreDbBuilder() + .WithLabel("Key", "Value"); + + var builder = baseBuilder + .WithImage(EventStoreContainerConfiguration.ImageName) + .WithName(EventStoreContainerConfiguration.Name) + .WithPortBinding(EventStoreContainerConfiguration.Port, true) + .Build(); + + return builder; + } + + public sealed class RabbitMqContainerOptions + { + public string Name { get; set; } = "rabbitmq_" + Guid.NewGuid(); + public int Port { get; set; } = 5672; + public int ApiPort { get; set; } = 15672; + public string ImageName { get; set; } = "rabbitmq:3-management"; + public string UserName { get; set; } = "guest"; + public string Password { get; set; } = "guest"; + } + + public sealed class PostgresContainerOptions + { + public string Name { get; set; } = "postgreSql_" + Guid.NewGuid().ToString("D"); + public int Port { get; set; } = 5432; + public string ImageName { get; set; } = "postgres:latest"; + public string UserName { get; set; } = Guid.NewGuid().ToString("D"); + public string Password { get; set; } = Guid.NewGuid().ToString("D"); + } + + public sealed class PostgresPersistContainerOptions + { + public string Name { get; set; } = "postgreSql_" + Guid.NewGuid().ToString("D"); + public int Port { get; set; } = 5432; + public string ImageName { get; set; } = "postgres:latest"; + public string UserName { get; set; } = Guid.NewGuid().ToString("D"); + public string Password { get; set; } = Guid.NewGuid().ToString("D"); + } + + public sealed class MongoContainerOptions + { + public string Name { get; set; } = "mongo_" + Guid.NewGuid().ToString("D"); + public int Port { get; set; } = 27017; + public string ImageName { get; set; } = "mongo:5"; + public string UserName { get; set; } = Guid.NewGuid().ToString("D"); + public string Password { get; set; } = Guid.NewGuid().ToString("D"); + } + + public sealed class EventStoreContainerOptions + { + public string Name { get; set; } = "event_store_" + Guid.NewGuid().ToString("D"); + public int Port { get; set; } = 2113; + public string ImageName { get; set; } = "eventstore/eventstore:21.2.0-buster-slim"; + } } diff --git a/src/Services/Booking/src/Booking/Extensions/Infrastructure/InfrastructureExtensions.cs b/src/Services/Booking/src/Booking/Extensions/Infrastructure/InfrastructureExtensions.cs index 76d1cfb..f3bee2a 100644 --- a/src/Services/Booking/src/Booking/Extensions/Infrastructure/InfrastructureExtensions.cs +++ b/src/Services/Booking/src/Booking/Extensions/Infrastructure/InfrastructureExtensions.cs @@ -1,7 +1,6 @@ using System.Threading.RateLimiting; using Booking.Data; using BuildingBlocks.Core; -using BuildingBlocks.EFCore; using BuildingBlocks.EventStoreDB; using BuildingBlocks.HealthCheck; using BuildingBlocks.IdsGenerator; @@ -27,6 +26,8 @@ using Serilog; namespace Booking.Extensions.Infrastructure; +using BuildingBlocks.PersistMessageProcessor.Data; + public static class InfrastructureExtensions { public static WebApplicationBuilder AddInfrastructure(this WebApplicationBuilder builder) @@ -99,6 +100,7 @@ public static class InfrastructureExtensions }); app.UseCorrelationId(); app.UseHttpMetrics(); + app.UseMigration(env); app.UseCustomHealthCheck(); app.MapMetrics(); app.MapGet("/", x => x.Response.WriteAsync(appOptions.Name)); diff --git a/src/Services/Booking/tests/IntegrationTest/Booking/Features/CreateBookingTests.cs b/src/Services/Booking/tests/IntegrationTest/Booking/Features/CreateBookingTests.cs index c129c77..0d1e711 100644 --- a/src/Services/Booking/tests/IntegrationTest/Booking/Features/CreateBookingTests.cs +++ b/src/Services/Booking/tests/IntegrationTest/Booking/Features/CreateBookingTests.cs @@ -1,11 +1,8 @@ -using System; -using System.Linq; +using System.Linq; using System.Threading.Tasks; using Booking.Api; using Booking.Data; using BuildingBlocks.Contracts.EventBus.Messages; -using BuildingBlocks.EFCore; -using BuildingBlocks.PersistMessageProcessor.Data; using BuildingBlocks.TestBase; using Flight; using FluentAssertions; @@ -21,72 +18,69 @@ using GetByIdRequest = Flight.GetByIdRequest; namespace Integration.Test.Booking.Features { - // todo: uncomment after event-store test-container is published. - // public class CreateBookingTests : BookingIntegrationTestBase - // { - // public CreateBookingTests(TestReadFixture integrationTestFixture) : base( - // integrationTestFixture) - // { - // } - // - // protected override void RegisterTestsServices(IServiceCollection services) - // { - // MockFlightGrpcServices(services); - // MockPassengerGrpcServices(services); - // } - // - // // todo: add support test for event-store - // [Fact] - // public async Task should_create_booking_to_event_store_currectly() - // { - // // Arrange - // var command = new FakeCreateBookingCommand().Generate(); - // - // // Act - // - // var response = await Fixture.SendAsync(command); - // - // // Assert - // response.Should().BeGreaterOrEqualTo(0); - // - // (await Fixture.WaitForPublishing()).Should().Be(true); - // } - // - // - // private void MockPassengerGrpcServices(IServiceCollection services) - // { - // services.Replace(ServiceDescriptor.Singleton(x => - // { - // var mockPassenger = Substitute.For(); - // - // mockPassenger.GetByIdAsync(Arg.Any()) - // .Returns(TestCalls.AsyncUnaryCall(Task.FromResult(new FakePassengerResponse().Generate()), - // Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { })); - // - // return mockPassenger; - // })); - // } - // - // private void MockFlightGrpcServices(IServiceCollection services) - // { - // services.Replace(ServiceDescriptor.Singleton(x => - // { - // var mockFlight = Substitute.For(); - // - // mockFlight.GetByIdAsync(Arg.Any()) - // .Returns(TestCalls.AsyncUnaryCall(Task.FromResult(new FakeFlightResponse().Generate()), - // Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { })); - // - // mockFlight.GetAvailableSeatsAsync(Arg.Any()) - // .Returns(TestCalls.AsyncUnaryCall(Task.FromResult(FakeSeatsResponse.Generate()), - // Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { })); - // - // mockFlight.ReserveSeatAsync(Arg.Any()) - // .Returns(TestCalls.AsyncUnaryCall(Task.FromResult(FakeSeatsResponse.Generate()?.Items?.First()), - // Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { })); - // - // return mockFlight; - // })); - // } - // } + public class CreateBookingTests : BookingIntegrationTestBase + { + public CreateBookingTests(TestReadFixture integrationTestFixture) : base( + integrationTestFixture) + { + } + + protected override void RegisterTestsServices(IServiceCollection services) + { + MockFlightGrpcServices(services); + MockPassengerGrpcServices(services); + } + + [Fact] + public async Task should_create_booking_to_event_store_currectly() + { + // Arrange + var command = new FakeCreateBookingCommand().Generate(); + + // Act + var response = await Fixture.SendAsync(command); + + // Assert + response.Should().BeGreaterOrEqualTo(0); + + (await Fixture.WaitForPublishing()).Should().Be(true); + } + + + private void MockPassengerGrpcServices(IServiceCollection services) + { + services.Replace(ServiceDescriptor.Singleton(x => + { + var mockPassenger = Substitute.For(); + + mockPassenger.GetByIdAsync(Arg.Any()) + .Returns(TestCalls.AsyncUnaryCall(Task.FromResult(new FakePassengerResponse().Generate()), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { })); + + return mockPassenger; + })); + } + + private void MockFlightGrpcServices(IServiceCollection services) + { + services.Replace(ServiceDescriptor.Singleton(x => + { + var mockFlight = Substitute.For(); + + mockFlight.GetByIdAsync(Arg.Any()) + .Returns(TestCalls.AsyncUnaryCall(Task.FromResult(new FakeFlightResponse().Generate()), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { })); + + mockFlight.GetAvailableSeatsAsync(Arg.Any()) + .Returns(TestCalls.AsyncUnaryCall(Task.FromResult(FakeSeatsResponse.Generate()), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { })); + + mockFlight.ReserveSeatAsync(Arg.Any()) + .Returns(TestCalls.AsyncUnaryCall(Task.FromResult(FakeSeatsResponse.Generate()?.Items?.First()), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { })); + + return mockFlight; + })); + } + } }