From 914d7f1bfb94fc480550a40251e699bdb0d88e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Ma=C3=B1es=20Medina?= Date: Fri, 14 Jun 2024 15:16:18 +0200 Subject: [PATCH 1/3] Create payments api --- .dockerignore | 25 +++++++++++++++++++ PaymentsApi/DependencyInjection.cs | 21 ++++++++++++++++ PaymentsApi/Dockerfile | 20 +++++++++++++++ .../dotNetTesting.Tests.csproj | 3 ++- dotNetTesting.sln | 12 +++++++++ dotNetTesting.sln.DotSettings.user | 10 +++++--- .../Payments/Domain/CreatePaymentUseCase.cs | 6 ++++- .../Payments/Domain/ICreatePaymentUseCase.cs | 8 ++++++ dotNetTesting/dotNetTesting.csproj | 2 +- global.json | 7 ++++++ 10 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 .dockerignore create mode 100644 PaymentsApi/DependencyInjection.cs create mode 100644 PaymentsApi/Dockerfile create mode 100644 dotNetTesting/Payments/Domain/ICreatePaymentUseCase.cs create mode 100644 global.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..38bece4 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/PaymentsApi/DependencyInjection.cs b/PaymentsApi/DependencyInjection.cs new file mode 100644 index 0000000..3b3f5b2 --- /dev/null +++ b/PaymentsApi/DependencyInjection.cs @@ -0,0 +1,21 @@ +using dotNetTesting.Payments; +using dotNetTesting.Payments.DataAccess; +using dotNetTesting.Services; +using Microsoft.EntityFrameworkCore; + +namespace PaymentsApi; + +public static class DependencyInjection +{ + public static void AddDependencies(this WebApplicationBuilder builder) + { + builder.Services.AddDbContextPool(options => + { + options.UseNpgsql("Host=localhost;Port=5432;Database=postgres;Username=postgres;Password=postgres;"); + }); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + } +} \ No newline at end of file diff --git a/PaymentsApi/Dockerfile b/PaymentsApi/Dockerfile new file mode 100644 index 0000000..5865eda --- /dev/null +++ b/PaymentsApi/Dockerfile @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["PaymentsApi/PaymentsApi.csproj", "PaymentsApi/"] +RUN dotnet restore "PaymentsApi/PaymentsApi.csproj" +COPY . . +WORKDIR "/src/PaymentsApi" +RUN dotnet build "PaymentsApi.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "PaymentsApi.csproj" -c Release -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "PaymentsApi.dll"] diff --git a/dotNetTesting.Tests/dotNetTesting.Tests.csproj b/dotNetTesting.Tests/dotNetTesting.Tests.csproj index cb9473f..e16b74c 100644 --- a/dotNetTesting.Tests/dotNetTesting.Tests.csproj +++ b/dotNetTesting.Tests/dotNetTesting.Tests.csproj @@ -1,9 +1,10 @@ - net7.0 false + + net8.0 diff --git a/dotNetTesting.sln b/dotNetTesting.sln index b2f4846..418216f 100644 --- a/dotNetTesting.sln +++ b/dotNetTesting.sln @@ -4,6 +4,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dotNetTesting", "dotNetTest EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dotNetTesting.Tests", "dotNetTesting.Tests\dotNetTesting.Tests.csproj", "{A36D0609-9572-44AF-95AD-01FECE04C0C8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PaymentsApi", "PaymentsApi\PaymentsApi.csproj", "{4575AA41-DAE8-47F0-B90A-A6FDA0103DBB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PaymentsApi.Tests", "PaymentsApi.Tests\PaymentsApi.Tests.csproj", "{746D49C0-1EF3-4EB1-A8B8-B59F8439E2AE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -18,5 +22,13 @@ Global {A36D0609-9572-44AF-95AD-01FECE04C0C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {A36D0609-9572-44AF-95AD-01FECE04C0C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {A36D0609-9572-44AF-95AD-01FECE04C0C8}.Release|Any CPU.Build.0 = Release|Any CPU + {4575AA41-DAE8-47F0-B90A-A6FDA0103DBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4575AA41-DAE8-47F0-B90A-A6FDA0103DBB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4575AA41-DAE8-47F0-B90A-A6FDA0103DBB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4575AA41-DAE8-47F0-B90A-A6FDA0103DBB}.Release|Any CPU.Build.0 = Release|Any CPU + {746D49C0-1EF3-4EB1-A8B8-B59F8439E2AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {746D49C0-1EF3-4EB1-A8B8-B59F8439E2AE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {746D49C0-1EF3-4EB1-A8B8-B59F8439E2AE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {746D49C0-1EF3-4EB1-A8B8-B59F8439E2AE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/dotNetTesting.sln.DotSettings.user b/dotNetTesting.sln.DotSettings.user index 688b81f..5633efc 100644 --- a/dotNetTesting.sln.DotSettings.user +++ b/dotNetTesting.sln.DotSettings.user @@ -3,7 +3,11 @@ d6790ab7-33c2-4425-b2c9-51480cd1a852 33ff99d8-b1ad-4ed5-a4fd-376b97c2c841 <SessionState ContinuousTestingMode="0" IsActive="True" Name="CreatePaymentUseCaseTest" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> - <TestAncestor> - <TestId>xUnit::A36D0609-9572-44AF-95AD-01FECE04C0C8::net7.0::dotNetTesting.Tests.Payments.DataAccess.EntitiesRepositoryTest</TestId> - </TestAncestor> + <Or> + <Project Location="/Users/adriamanesmedina/Documents/agilogy/trainings/dotNetTesting/dotNetTesting.Tests" Presentation="&lt;dotNetTesting.Tests&gt;" /> + <TestAncestor> + <TestId>xUnit::746D49C0-1EF3-4EB1-A8B8-B59F8439E2AE::net8.0::PaymentsApi.Tests.PaymentsApiShould.Test1</TestId> + <TestId>xUnit::746D49C0-1EF3-4EB1-A8B8-B59F8439E2AE::net8.0::PaymentsApi.Tests.PaymentsApiShould</TestId> + </TestAncestor> + </Or> </SessionState> \ No newline at end of file diff --git a/dotNetTesting/Payments/Domain/CreatePaymentUseCase.cs b/dotNetTesting/Payments/Domain/CreatePaymentUseCase.cs index 9da7dc6..6d15366 100644 --- a/dotNetTesting/Payments/Domain/CreatePaymentUseCase.cs +++ b/dotNetTesting/Payments/Domain/CreatePaymentUseCase.cs @@ -3,7 +3,9 @@ namespace dotNetTesting.Payments; -public class CreatePaymentUseCase + + +public class CreatePaymentUseCase : ICreatePaymentUseCase { private readonly IGuidGenerator _guidGenerator; private readonly IPaymentsRepository _paymentsRepository; @@ -37,6 +39,8 @@ public async Task Invoke(CreatePaymentRequest request) } } + + public record CreatePaymentRequest(MonetaryAmount Amount, EntityId Payer, EntityId Payee); public class PayerDoesNotExist : Exception diff --git a/dotNetTesting/Payments/Domain/ICreatePaymentUseCase.cs b/dotNetTesting/Payments/Domain/ICreatePaymentUseCase.cs new file mode 100644 index 0000000..c49dc2c --- /dev/null +++ b/dotNetTesting/Payments/Domain/ICreatePaymentUseCase.cs @@ -0,0 +1,8 @@ +using dotNetTesting.Payments.Model; + +namespace dotNetTesting.Payments; + +public interface ICreatePaymentUseCase +{ + public Task Invoke(CreatePaymentRequest request); +} \ No newline at end of file diff --git a/dotNetTesting/dotNetTesting.csproj b/dotNetTesting/dotNetTesting.csproj index a247a7a..9ca29e0 100644 --- a/dotNetTesting/dotNetTesting.csproj +++ b/dotNetTesting/dotNetTesting.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable enable diff --git a/global.json b/global.json new file mode 100644 index 0000000..b5b37b6 --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "8.0.0", + "rollForward": "latestMajor", + "allowPrerelease": false + } +} \ No newline at end of file From bf505ece54631ac7c742bc6232ded4eebb2e1518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Ma=C3=B1es=20Medina?= Date: Mon, 17 Jun 2024 10:44:59 +0200 Subject: [PATCH 2/3] Add missing files --- PaymentsApi.Tests/GlobalUsings.cs | 1 + PaymentsApi.Tests/PaymentsApi.Tests.csproj | 30 ++++++++++++ PaymentsApi.Tests/PaymentsApiShould.cs | 54 ++++++++++++++++++++++ PaymentsApi/PaymentsApi.csproj | 25 ++++++++++ PaymentsApi/PaymentsApi.http | 6 +++ PaymentsApi/Program.cs | 26 +++++++++++ PaymentsApi/Properties/launchSettings.json | 41 ++++++++++++++++ PaymentsApi/appsettings.Development.json | 8 ++++ PaymentsApi/appsettings.json | 9 ++++ 9 files changed, 200 insertions(+) create mode 100644 PaymentsApi.Tests/GlobalUsings.cs create mode 100644 PaymentsApi.Tests/PaymentsApi.Tests.csproj create mode 100644 PaymentsApi.Tests/PaymentsApiShould.cs create mode 100644 PaymentsApi/PaymentsApi.csproj create mode 100644 PaymentsApi/PaymentsApi.http create mode 100644 PaymentsApi/Program.cs create mode 100644 PaymentsApi/Properties/launchSettings.json create mode 100644 PaymentsApi/appsettings.Development.json create mode 100644 PaymentsApi/appsettings.json diff --git a/PaymentsApi.Tests/GlobalUsings.cs b/PaymentsApi.Tests/GlobalUsings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/PaymentsApi.Tests/GlobalUsings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/PaymentsApi.Tests/PaymentsApi.Tests.csproj b/PaymentsApi.Tests/PaymentsApi.Tests.csproj new file mode 100644 index 0000000..d5744c4 --- /dev/null +++ b/PaymentsApi.Tests/PaymentsApi.Tests.csproj @@ -0,0 +1,30 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/PaymentsApi.Tests/PaymentsApiShould.cs b/PaymentsApi.Tests/PaymentsApiShould.cs new file mode 100644 index 0000000..7375fc7 --- /dev/null +++ b/PaymentsApi.Tests/PaymentsApiShould.cs @@ -0,0 +1,54 @@ +using System.Net.Http.Headers; +using dotNetTesting.Payments; +using dotNetTesting.Payments.Model; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Hosting; +using Newtonsoft.Json; +using JsonSerializer = System.Text.Json.JsonSerializer; + +namespace PaymentsApi.Tests; + +public class FakeCreatePaymentUseCase : ICreatePaymentUseCase +{ + public Task Invoke(CreatePaymentRequest request) + { + return new Task(() => new PaymentId("1234")); + } +} + +public class PaymentsApiShould +{ + private HttpClient _testClient; + public PaymentsApiShould() + { + var builder = WebApplication.CreateBuilder(); + builder.AddDependencies(); + builder.Services.Replace(new ServiceDescriptor(typeof(ICreatePaymentUseCase), new FakeCreatePaymentUseCase())); + builder.WebHost.UseTestServer(); + var app = builder.Build(); + app.Start(); + _testClient = app.GetTestClient(); + } + + [Fact] + public async void Test1() + { + var request = new CreatePaymentRequest( + new MonetaryAmount(10, Currency.Eur), new EntityId("Halcon"), new EntityId("Hotel") + ); + var jsonRequest = JsonSerializer.Serialize(request); + var content = new StringContent(jsonRequest); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + var response = await _testClient.PostAsync("/payments", content); + var responseContent = await response.Content.ReadAsStringAsync(); + var paymentId = JsonConvert.DeserializeObject(responseContent); + + + //response.EnsureSuccessStatusCode(); + Assert.Equal(new PaymentId("1234"), paymentId); + + } +} \ No newline at end of file diff --git a/PaymentsApi/PaymentsApi.csproj b/PaymentsApi/PaymentsApi.csproj new file mode 100644 index 0000000..156bfc4 --- /dev/null +++ b/PaymentsApi/PaymentsApi.csproj @@ -0,0 +1,25 @@ + + + + net8.0 + enable + enable + Linux + + + + + + + + + + .dockerignore + + + + + + + + diff --git a/PaymentsApi/PaymentsApi.http b/PaymentsApi/PaymentsApi.http new file mode 100644 index 0000000..a2c5c2b --- /dev/null +++ b/PaymentsApi/PaymentsApi.http @@ -0,0 +1,6 @@ +@PaymentsApi_HostAddress = http://localhost:5183 + +POST {{PaymentsApi_HostAddress}}/payments/ +Accept: application/json + +### diff --git a/PaymentsApi/Program.cs b/PaymentsApi/Program.cs new file mode 100644 index 0000000..8201da1 --- /dev/null +++ b/PaymentsApi/Program.cs @@ -0,0 +1,26 @@ +using dotNetTesting.Payments; +using PaymentsApi; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); + + +builder.AddDependencies(); + +var app = builder.Build(); +app.UseHttpsRedirection(); + + +app.MapPost("/payments", async (CreatePaymentRequest request, ICreatePaymentUseCase useCase) => +{ + var res = await useCase.Invoke(request); + return Results.Created($"/payments/{res.Value}", res.Value); +}); + +app.MapGet("/", () => Results.Ok("Hello world")); + + +app.Run(); \ No newline at end of file diff --git a/PaymentsApi/Properties/launchSettings.json b/PaymentsApi/Properties/launchSettings.json new file mode 100644 index 0000000..bd32e53 --- /dev/null +++ b/PaymentsApi/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:46945", + "sslPort": 44388 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5183", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7019;http://localhost:5183", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/PaymentsApi/appsettings.Development.json b/PaymentsApi/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/PaymentsApi/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/PaymentsApi/appsettings.json b/PaymentsApi/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/PaymentsApi/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} From d11b9701fe84313437abaf4a6b001be3ea9ebce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Ma=C3=B1es=20Medina?= Date: Tue, 18 Jun 2024 20:34:37 +0200 Subject: [PATCH 3/3] Extract endpoints to static class --- PaymentsApi.Tests/PaymentsApiShould.cs | 4 +++- PaymentsApi/Endpoints.cs | 17 +++++++++++++++++ PaymentsApi/Program.cs | 11 +---------- dotNetTesting.sln.DotSettings.user | 15 ++++++--------- 4 files changed, 27 insertions(+), 20 deletions(-) create mode 100644 PaymentsApi/Endpoints.cs diff --git a/PaymentsApi.Tests/PaymentsApiShould.cs b/PaymentsApi.Tests/PaymentsApiShould.cs index 7375fc7..e34de73 100644 --- a/PaymentsApi.Tests/PaymentsApiShould.cs +++ b/PaymentsApi.Tests/PaymentsApiShould.cs @@ -21,7 +21,7 @@ public Task Invoke(CreatePaymentRequest request) public class PaymentsApiShould { - private HttpClient _testClient; + private readonly HttpClient _testClient; public PaymentsApiShould() { var builder = WebApplication.CreateBuilder(); @@ -29,8 +29,10 @@ public PaymentsApiShould() builder.Services.Replace(new ServiceDescriptor(typeof(ICreatePaymentUseCase), new FakeCreatePaymentUseCase())); builder.WebHost.UseTestServer(); var app = builder.Build(); + app.UseEndpoints(); app.Start(); _testClient = app.GetTestClient(); + _testClient.Timeout = TimeSpan.FromSeconds(10); } [Fact] diff --git a/PaymentsApi/Endpoints.cs b/PaymentsApi/Endpoints.cs new file mode 100644 index 0000000..9a6b57e --- /dev/null +++ b/PaymentsApi/Endpoints.cs @@ -0,0 +1,17 @@ +using dotNetTesting.Payments; + +namespace PaymentsApi; + +public static class Endpoints +{ + public static void UseEndpoints(this WebApplication webApplication) + { + webApplication.MapPost("/payments", async (CreatePaymentRequest request, ICreatePaymentUseCase useCase) => + { + var res = await useCase.Invoke(request); + return Results.Created($"/payments/{res.Value}", res.Value); + }); + + webApplication.MapGet("/", () => Results.Ok("Hello world")); + } +} \ No newline at end of file diff --git a/PaymentsApi/Program.cs b/PaymentsApi/Program.cs index 8201da1..3b043d8 100644 --- a/PaymentsApi/Program.cs +++ b/PaymentsApi/Program.cs @@ -1,4 +1,3 @@ -using dotNetTesting.Payments; using PaymentsApi; var builder = WebApplication.CreateBuilder(args); @@ -9,18 +8,10 @@ builder.AddDependencies(); - var app = builder.Build(); app.UseHttpsRedirection(); - -app.MapPost("/payments", async (CreatePaymentRequest request, ICreatePaymentUseCase useCase) => -{ - var res = await useCase.Invoke(request); - return Results.Created($"/payments/{res.Value}", res.Value); -}); - -app.MapGet("/", () => Results.Ok("Hello world")); +app.UseEndpoints(); app.Run(); \ No newline at end of file diff --git a/dotNetTesting.sln.DotSettings.user b/dotNetTesting.sln.DotSettings.user index 5633efc..5338e5e 100644 --- a/dotNetTesting.sln.DotSettings.user +++ b/dotNetTesting.sln.DotSettings.user @@ -2,12 +2,9 @@ A36D0609-9572-44AF-95AD-01FECE04C0C8 d6790ab7-33c2-4425-b2c9-51480cd1a852 33ff99d8-b1ad-4ed5-a4fd-376b97c2c841 - <SessionState ContinuousTestingMode="0" IsActive="True" Name="CreatePaymentUseCaseTest" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> - <Or> - <Project Location="/Users/adriamanesmedina/Documents/agilogy/trainings/dotNetTesting/dotNetTesting.Tests" Presentation="&lt;dotNetTesting.Tests&gt;" /> - <TestAncestor> - <TestId>xUnit::746D49C0-1EF3-4EB1-A8B8-B59F8439E2AE::net8.0::PaymentsApi.Tests.PaymentsApiShould.Test1</TestId> - <TestId>xUnit::746D49C0-1EF3-4EB1-A8B8-B59F8439E2AE::net8.0::PaymentsApi.Tests.PaymentsApiShould</TestId> - </TestAncestor> - </Or> -</SessionState> \ No newline at end of file + <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from PaymentsApiShould.cs" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <ProjectFile>746D49C0-1EF3-4EB1-A8B8-B59F8439E2AE/f:PaymentsApiShould.cs</ProjectFile> +</SessionState> + + + \ No newline at end of file