diff --git a/src/BuildingBlocks/BuildingBlocks.csproj b/src/BuildingBlocks/BuildingBlocks.csproj index 5279832..d9b84d7 100644 --- a/src/BuildingBlocks/BuildingBlocks.csproj +++ b/src/BuildingBlocks/BuildingBlocks.csproj @@ -22,7 +22,6 @@ - @@ -51,7 +50,6 @@ - @@ -120,6 +118,10 @@ + + + + diff --git a/src/BuildingBlocks/Contracts/Grpc/FlightGrpcContracts.cs b/src/BuildingBlocks/Contracts/Grpc/FlightGrpcContracts.cs index 24ddeda..1ea0e44 100644 --- a/src/BuildingBlocks/Contracts/Grpc/FlightGrpcContracts.cs +++ b/src/BuildingBlocks/Contracts/Grpc/FlightGrpcContracts.cs @@ -8,7 +8,7 @@ namespace BuildingBlocks.Contracts.Grpc; { UnaryResult GetById(long id); UnaryResult> GetAvailableSeats(long flightId); - UnaryResult ReserveSeat(ReserveSeatRequestDto request); + UnaryResult ReserveSeat(ReserveSeatRequestDto request); } diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommandHandler.cs b/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommandHandler.cs index 82b42d3..0776d67 100644 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommandHandler.cs +++ b/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommandHandler.cs @@ -26,10 +26,13 @@ public class CreateBookingCommandHandler : IRequestHandler(() => MagicOnionClient.Create(channelFlight)).Value; + _flightGrpcService = + new Lazy(() => MagicOnionClient.Create(channelFlight)).Value; var channelPassenger = GrpcChannel.ForAddress(grpcOptions.Value.PassengerAddress); - _passengerGrpcService = new Lazy(() => MagicOnionClient.Create(channelPassenger)).Value; + _passengerGrpcService = + new Lazy(() => MagicOnionClient.Create(channelPassenger)) + .Value; } public async Task Handle(CreateBookingCommand command, @@ -38,8 +41,10 @@ public class CreateBookingCommandHandler : IRequestHandler, IFlightGrpcSer return result.Adapt>(); } - public async UnaryResult ReserveSeat(ReserveSeatRequestDto request) + public async UnaryResult ReserveSeat(ReserveSeatRequestDto request) { var result = await _mediator.Send(new ReserveSeatCommand(request.FlightId, request.SeatNumber)); - return result.Adapt(); + return result.Adapt(); } } diff --git a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateSeatCommand.cs b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateSeatCommand.cs new file mode 100644 index 0000000..54546ff --- /dev/null +++ b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateSeatCommand.cs @@ -0,0 +1,14 @@ +using AutoBogus; +using BuildingBlocks.IdsGenerator; +using Flight.Seats.Features.CreateSeat; + +namespace Integration.Test.Fakes; + +public class FakeCreateSeatCommand : AutoFaker +{ + public FakeCreateSeatCommand(long flightId) + { + RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId()); + RuleFor(r => r.FlightId, _ => flightId); + } +} diff --git a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeSeatCreated.cs b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeSeatCreated.cs new file mode 100644 index 0000000..74af85c --- /dev/null +++ b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeSeatCreated.cs @@ -0,0 +1,13 @@ +using Flight.Seats.Features.CreateSeat; +using Flight.Seats.Models; + +namespace Integration.Test.Fakes; + +public static class FakeSeatCreated +{ + public static Seat Generate(CreateSeatCommand command) + { + return Seat.Create(command.Id, command.SeatNumber, command.Type, command.Class, command.FlightId); + } +} + diff --git a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableFlightsTests.cs b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableFlightsTests.cs index 7f0a561..5d08d1d 100644 --- a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableFlightsTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableFlightsTests.cs @@ -1,8 +1,11 @@ using System.Linq; using System.Threading.Tasks; +using BuildingBlocks.Contracts.Grpc; using Flight.Flights.Features.GetAvailableFlights; using FluentAssertions; +using Grpc.Net.Client; using Integration.Test.Fakes; +using MagicOnion.Client; using Xunit; namespace Integration.Test.Flight.Features; @@ -11,10 +14,12 @@ namespace Integration.Test.Flight.Features; public class GetAvailableFlightsTests { private readonly TestFixture _fixture; + private readonly GrpcChannel _channel; public GetAvailableFlightsTests(TestFixture fixture) { _fixture = fixture; + _channel = fixture.Channel; } [Fact] diff --git a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableSeatsTests.cs b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableSeatsTests.cs new file mode 100644 index 0000000..6f7fda0 --- /dev/null +++ b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableSeatsTests.cs @@ -0,0 +1,50 @@ +using System.Linq; +using System.Threading.Tasks; +using BuildingBlocks.Contracts.Grpc; +using Flight.Flights.Features.GetAvailableFlights; +using FluentAssertions; +using Grpc.Net.Client; +using Integration.Test.Fakes; +using MagicOnion.Client; +using Xunit; + +namespace Integration.Test.Flight.Features; + +[Collection(nameof(TestFixture))] +public class GetAvailableSeatsTests +{ + private readonly TestFixture _fixture; + private readonly GrpcChannel _channel; + + public GetAvailableSeatsTests(TestFixture fixture) + { + _fixture = fixture; + _channel = fixture.Channel; + } + + [Fact] + public async Task should_return_available_seats_from_grpc_service() + { + // Arrange + var flightCommand = new FakeCreateFlightCommand().Generate(); + var flightEntity = FakeFlightCreated.Generate(flightCommand); + + await _fixture.InsertAsync(flightEntity); + + var seatCommand1 = new FakeCreateSeatCommand(flightEntity.Id).Generate(); + var seatCommand2 = new FakeCreateSeatCommand(flightEntity.Id).Generate(); + var seatEntity1 = FakeSeatCreated.Generate(seatCommand1); + var seatEntity2 = FakeSeatCreated.Generate(seatCommand2); + + await _fixture.InsertAsync(seatEntity1, seatEntity2); + + var flightGrpcClient = MagicOnionClient.Create(_channel); + + // Act + var response = await flightGrpcClient.GetAvailableSeats(flightEntity.Id); + + // Assert + response?.Should().NotBeNull(); + response?.Count().Should().BeGreaterOrEqualTo(2); + } +} diff --git a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs index 489356c..e639559 100644 --- a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs @@ -1,7 +1,10 @@ using System.Threading.Tasks; +using BuildingBlocks.Contracts.Grpc; using Flight.Flights.Features.GetFlightById; using FluentAssertions; +using Grpc.Net.Client; using Integration.Test.Fakes; +using MagicOnion.Client; using Xunit; namespace Integration.Test.Flight.Features; @@ -10,10 +13,12 @@ namespace Integration.Test.Flight.Features; public class GetFlightByIdTests { private readonly TestFixture _fixture; + private readonly GrpcChannel _channel; public GetFlightByIdTests(TestFixture fixture) { _fixture = fixture; + _channel = fixture.Channel; } [Fact] @@ -33,4 +38,22 @@ public class GetFlightByIdTests response.Should().NotBeNull(); response?.Id.Should().Be(flightEntity.Id); } + + [Fact] + public async Task should_retrive_a_flight_by_id_from_grpc_service() + { + // Arrange + var command = new FakeCreateFlightCommand().Generate(); + var flightEntity = FakeFlightCreated.Generate(command); + await _fixture.InsertAsync(flightEntity); + + var flightGrpcClient = MagicOnionClient.Create(_channel); + + // Act + var response = await flightGrpcClient.GetById(flightEntity.Id); + + // Assert + response?.Should().NotBeNull(); + response?.Id.Should().Be(flightEntity.Id); + } } diff --git a/src/Services/Flight/tests/IntegrationTest/Flight/Features/ReserveSeatTests.cs b/src/Services/Flight/tests/IntegrationTest/Flight/Features/ReserveSeatTests.cs new file mode 100644 index 0000000..8ca2505 --- /dev/null +++ b/src/Services/Flight/tests/IntegrationTest/Flight/Features/ReserveSeatTests.cs @@ -0,0 +1,48 @@ +using System.Linq; +using System.Threading.Tasks; +using BuildingBlocks.Contracts.Grpc; +using FluentAssertions; +using Grpc.Net.Client; +using Integration.Test.Fakes; +using MagicOnion.Client; +using Xunit; + +namespace Integration.Test.Flight.Features; + +[Collection(nameof(TestFixture))] +public class ReserveSeatTests +{ + private readonly TestFixture _fixture; + private readonly GrpcChannel _channel; + + public ReserveSeatTests(TestFixture fixture) + { + _fixture = fixture; + _channel = fixture.Channel; + } + + [Fact] + public async Task should_return_valid_reserve_seat_from_grpc_service() + { + // Arrange + var flightCommand = new FakeCreateFlightCommand().Generate(); + var flightEntity = FakeFlightCreated.Generate(flightCommand); + + await _fixture.InsertAsync(flightEntity); + + var seatCommand = new FakeCreateSeatCommand(flightEntity.Id).Generate(); + var seatEntity = FakeSeatCreated.Generate(seatCommand); + + await _fixture.InsertAsync(seatEntity); + + var flightGrpcClient = MagicOnionClient.Create(_channel); + + // Act + var response = await flightGrpcClient.ReserveSeat(new ReserveSeatRequestDto{ FlightId = seatEntity.FlightId, SeatNumber = seatEntity.SeatNumber }); + + // Assert + response?.Should().NotBeNull(); + response?.SeatNumber.Should().Be(seatEntity.SeatNumber); + response?.FlightId.Should().Be(seatEntity.FlightId); + } +} diff --git a/src/Services/Flight/tests/IntegrationTest/TestFixture.cs b/src/Services/Flight/tests/IntegrationTest/TestFixture.cs index de307a6..34c5761 100644 --- a/src/Services/Flight/tests/IntegrationTest/TestFixture.cs +++ b/src/Services/Flight/tests/IntegrationTest/TestFixture.cs @@ -1,5 +1,6 @@ using System; using System.Net.Http; +using System.Threading.Channels; using System.Threading.Tasks; using BuildingBlocks.Domain.Model; using BuildingBlocks.EFCore; @@ -7,6 +8,8 @@ using BuildingBlocks.MassTransit; using BuildingBlocks.Web; using Flight.Data; using Flight.Data.Seed; +using Flight.GrpcServer; +using Grpc.Net.Client; using MassTransit; using MassTransit.Testing; using MediatR; @@ -43,9 +46,10 @@ public class TestFixture : IAsyncLifetime private IServiceScopeFactory _scopeFactory; private HttpClient _httpClient; private ITestHarness _testHarness; + private GrpcChannel _channel; public ITestHarness TestHarness => _testHarness; - + public GrpcChannel Channel => _channel; public async Task InitializeAsync() { @@ -83,6 +87,11 @@ public class TestFixture : IAsyncLifetime _httpClient = _factory.CreateClient(new WebApplicationFactoryClientOptions {AllowAutoRedirect = false}); + _channel = GrpcChannel.ForAddress(_httpClient.BaseAddress!, new GrpcChannelOptions + { + HttpClient = _httpClient + }); + _checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; await EnsureDatabaseAsync(); diff --git a/src/Services/Identity/tests/IntegrationTest/TestFixture.cs b/src/Services/Identity/tests/IntegrationTest/TestFixture.cs index 4eb9531..759214f 100644 --- a/src/Services/Identity/tests/IntegrationTest/TestFixture.cs +++ b/src/Services/Identity/tests/IntegrationTest/TestFixture.cs @@ -5,6 +5,7 @@ using BuildingBlocks.Domain.Model; using BuildingBlocks.EFCore; using BuildingBlocks.MassTransit; using BuildingBlocks.Web; +using Grpc.Net.Client; using Identity.Data; using MassTransit; using MassTransit.Testing; @@ -40,9 +41,9 @@ public class TestFixture : IAsyncLifetime private WebApplicationFactory _factory; private HttpClient _httpClient; private IServiceScopeFactory _scopeFactory; - + private GrpcChannel _channel; public ITestHarness TestHarness { get; private set; } - + public GrpcChannel Channel => _channel; public async Task InitializeAsync() { @@ -80,6 +81,8 @@ public class TestFixture : IAsyncLifetime _httpClient = _factory.CreateClient(new WebApplicationFactoryClientOptions {AllowAutoRedirect = false}); + _channel = GrpcChannel.ForAddress(_httpClient.BaseAddress!, new GrpcChannelOptions {HttpClient = _httpClient}); + _checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; await EnsureDatabaseAsync(); diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs new file mode 100644 index 0000000..69b4d39 --- /dev/null +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs @@ -0,0 +1,12 @@ +using AutoMapper; +using Mapster; +using Passenger.Passengers.Dtos; + +namespace Passenger.Passengers.Features; + +public class PassengerMappings : IRegister +{ + public void Register(TypeAdapterConfig config) + { + } +} diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/ReservationMappings.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/ReservationMappings.cs deleted file mode 100644 index 83a60e4..0000000 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/ReservationMappings.cs +++ /dev/null @@ -1,12 +0,0 @@ -using AutoMapper; -using Passenger.Passengers.Dtos; - -namespace Passenger.Passengers.Features; - -public class ReservationMappings: Profile -{ - public ReservationMappings() - { - CreateMap(); - } -} diff --git a/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs b/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs index b78a923..39b8e7f 100644 --- a/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs +++ b/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs @@ -1,7 +1,10 @@ using System.Threading.Tasks; using BuildingBlocks.Contracts.EventBus.Messages; +using BuildingBlocks.Contracts.Grpc; using FluentAssertions; +using Grpc.Net.Client; using Integration.Test.Fakes; +using MagicOnion.Client; using MassTransit.Testing; using Passenger.Passengers.Features.GetPassengerById; using Xunit; @@ -13,11 +16,13 @@ public class GetPassengerByIdTests { private readonly TestFixture _fixture; private readonly ITestHarness _testHarness; + private readonly GrpcChannel _channel; public GetPassengerByIdTests(TestFixture fixture) { _fixture = fixture; _testHarness = _fixture.TestHarness; + _channel = _fixture.Channel; } [Fact] @@ -39,4 +44,24 @@ public class GetPassengerByIdTests response.Should().NotBeNull(); response?.Id.Should().Be(passengerEntity.Id); } + + [Fact] + public async Task should_retrive_a_passenger_by_id_from_grpc_service() + { + // Arrange + var userCreated = new FakeUserCreated().Generate(); + await _testHarness.Bus.Publish(userCreated); + await _testHarness.Consumed.Any(); + var passengerEntity = FakePassengerCreated.Generate(userCreated); + await _fixture.InsertAsync(passengerEntity); + + var passengerGrpcClient = MagicOnionClient.Create(_channel); + + // Act + var response = await passengerGrpcClient.GetById(passengerEntity.Id); + + // Assert + response?.Should().NotBeNull(); + response?.Id.Should().Be(passengerEntity.Id); + } } diff --git a/src/Services/Passenger/tests/IntegrationTest/TestFixture.cs b/src/Services/Passenger/tests/IntegrationTest/TestFixture.cs index 9efe577..18f52cb 100644 --- a/src/Services/Passenger/tests/IntegrationTest/TestFixture.cs +++ b/src/Services/Passenger/tests/IntegrationTest/TestFixture.cs @@ -5,6 +5,7 @@ using BuildingBlocks.Domain.Model; using BuildingBlocks.EFCore; using BuildingBlocks.MassTransit; using BuildingBlocks.Web; +using Grpc.Net.Client; using MassTransit; using MassTransit.Testing; using MediatR; @@ -40,9 +41,9 @@ public class TestFixture : IAsyncLifetime private WebApplicationFactory _factory; private HttpClient _httpClient; private IServiceScopeFactory _scopeFactory; - + private GrpcChannel _channel; public ITestHarness TestHarness { get; private set; } - + public GrpcChannel Channel => _channel; public async Task InitializeAsync() { @@ -79,6 +80,8 @@ public class TestFixture : IAsyncLifetime _httpClient = _factory.CreateClient(new WebApplicationFactoryClientOptions {AllowAutoRedirect = false}); + _channel = GrpcChannel.ForAddress(_httpClient.BaseAddress!, new GrpcChannelOptions {HttpClient = _httpClient}); + _checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; await EnsureDatabaseAsync();