Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CooperaSharp/CooperaSharp.Service/.dockerignore
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions CooperaSharp/CooperaSharp.Service/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.idea/
bin/
obj/
*.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net9.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2025.2.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.6.6" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CooperaSharp.Service\CooperaSharp.Service.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
using System;
using Xunit;

namespace CooperaSharp.Service.Tests;

public class PedidoServiceTests
{
private class FakeClienteRepository : IClienteRepository
{
public Client? ClienteToReturn;
public int LastRequestedId;
public Client ObterPorId(int dtoClienteId)
{
LastRequestedId = dtoClienteId;
return ClienteToReturn!;
}
}

private class FakePedidoRepository : IPedidoRepository
{
public Pedido? SavedPedido;
public void Salvar(Pedido pedido)
{
SavedPedido = pedido;
}
}

private class FakeEstoqueService : IEstoqueService
{
public object ReservedItens;
public void ReservarItens(object itens)
{
ReservedItens = itens;
}
}

private class FakePagamentoService : IPagamentoService
{
public bool Result = true;
public object? LastPedido;
public bool Processar(object pedido)
{
LastPedido = pedido;
return Result;
}
}

private class FakeEmailService : IEmailService
{
public object? LastEmail;
public void EnviarConfirmacao(object email)
{
LastEmail = email;
}
}

private class FakeNotificacaoService : INotificacaoService
{
public string? LastMessage;
public void Enviar(string falhaNoPagamento)
{
LastMessage = falhaNoPagamento;
}
}

private class FakeLogger : ILogger
{
public string? LastLog;
public void Log(string clienteNaoEncontrado)
{
LastLog = clienteNaoEncontrado;
}
}

private class FakeFreteService : IFreteService
{
public object? LastEndereco;
public object ValorToReturn = 10m;
public object CalcularFrete(string dtoEnderecoEntrega)
{
LastEndereco = dtoEnderecoEntrega;
return ValorToReturn;
}
}

private class FakeMapper : IMapper
{
public Pedido? LastPedidoCreated;
public T Map<T>(PedidoDto dto)
{
var pedido = new Pedido
{
Id = 123,
Itens = new object()
};
LastPedidoCreated = pedido;
return (T)(object)pedido;
}
}

private class FakeAuditoria : IAuditoriaService
{
public (string? Acao, object? Id)? LastRegistro;
public void Registrar(string pedidoCriado, object toString)
{
LastRegistro = (pedidoCriado, toString);
}
}

private static PedidoService CreateService(
FakePedidoRepository pedidoRepo,
FakeEstoqueService estoque,
FakePagamentoService pagamento,
FakeNotificacaoService notificacao,
FakeFreteService frete,
FakeMapper mapper,
FakeAuditoria auditoria)
{
return new PedidoService(
clientecliente,
pedidoRepo,
estoque,
pagamento,
notificacao,
frete,
mapper,
auditoria);
}

[Fact]
public void ProcessarPedido_ClienteNaoEncontrado_DeveLogarENaoProsseguir()
{
var clienteRepo = new FakeClienteRepository { ClienteToReturn = null };
var pedidoRepo = new FakePedidoRepository();
var estoque = new FakeEstoqueService();
var pagamento = new FakePagamentoService();
var email = new FakeEmailService();
var notificacao = new FakeNotificacaoService();
var logger = new FakeLogger();
var frete = new FakeFreteService();
var mapper = new FakeMapper();
var auditoria = new FakeAuditoria();
var service = CreateService(clienteRepo, pedidoRepo, estoque, pagamento, email, notificacao, logger, frete, mapper, auditoria);

var dto = new PedidoDto { ClienteId = 1, EnderecoEntrega = "Rua 1" };

service.ProcessarPedido(dto);

Assert.Equal("Cliente não encontrado", logger.LastLog);
Assert.Null(mapper.LastPedidoCreated);
Assert.Null(estoque.ReservedItens);
Assert.Null(pagamento.LastPedido);
Assert.Null(pedidoRepo.SavedPedido);
Assert.Null(email.LastEmail);
Assert.Null(auditoria.LastRegistro);
Assert.Null(notificacao.LastMessage);
}

[Fact]
public void ProcessarPedido_PagamentoFalha_DeveNotificarENaoSalvarNemEnviarEmail()
{
var clienteRepo = new FakeClienteRepository { ClienteToReturn = new Client { Email = "[email protected]" } };
var pedidoRepo = new FakePedidoRepository();
var estoque = new FakeEstoqueService();
var pagamento = new FakePagamentoService { Result = false };
var email = new FakeEmailService();
var notificacao = new FakeNotificacaoService();
var logger = new FakeLogger();
var frete = new FakeFreteService { ValorToReturn = 42m };
var mapper = new FakeMapper();
var auditoria = new FakeAuditoria();
var service = CreateService(clienteRepo, pedidoRepo, estoque, pagamento, email, notificacao, logger, frete, mapper, auditoria);

var dto = new PedidoDto { ClienteId = 1, EnderecoEntrega = "Rua 2" };

service.ProcessarPedido(dto);

// Fez etapas até pagamento
Assert.NotNull(mapper.LastPedidoCreated);
Assert.Equal(mapper.LastPedidoCreated!.Itens, estoque.ReservedItens);
Assert.Equal("Rua 2", frete.LastEndereco);
// Notificou falha
Assert.Equal("Falha no pagamento", notificacao.LastMessage);
// Não salvou nem enviou email nem auditou
Assert.Null(pedidoRepo.SavedPedido);
Assert.Null(email.LastEmail);
Assert.Null(auditoria.LastRegistro);
}

[Fact]
public void ProcessarPedido_Sucesso_DeveExecutarTodoFluxo()
{
var clienteRepo = new FakeClienteRepository { ClienteToReturn = new Client { Email = "[email protected]" } };
var pedidoRepo = new FakePedidoRepository();
var estoque = new FakeEstoqueService();
var pagamento = new FakePagamentoService { Result = true };
var email = new FakeEmailService();
var notificacao = new FakeNotificacaoService();
var logger = new FakeLogger();
var frete = new FakeFreteService { ValorToReturn = 99m };
var mapper = new FakeMapper();
var auditoria = new FakeAuditoria();
var service = CreateService(clienteRepo, pedidoRepo, estoque, pagamento, email, notificacao, logger, frete, mapper, auditoria);

var dto = new PedidoDto { ClienteId = 77, EnderecoEntrega = "Rua 3" };

service.ProcessarPedido(dto);

// Reservou itens
Assert.Equal(mapper.LastPedidoCreated!.Itens, estoque.ReservedItens);
// Calculou frete e adicionou
Assert.Equal("Rua 3", frete.LastEndereco);
Assert.Equal(99m, mapper.LastPedidoCreated!.Frete);
// Processou pagamento com o pedido
Assert.Same(mapper.LastPedidoCreated, pagamento.LastPedido);
// Salvou
Assert.Same(mapper.LastPedidoCreated, pedidoRepo.SavedPedido);
// Enviou email
Assert.Equal("[email protected]", email.LastEmail);
// Auditou
Assert.Equal(("Pedido criado", "123"), auditoria.LastRegistro);
// Não deve ter registrado erro/notificação extra
Assert.Null(logger.LastLog);
Assert.Null(notificacao.LastMessage);
}
}
27 changes: 27 additions & 0 deletions CooperaSharp/CooperaSharp.Service/CooperaSharp.Service.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CooperaSharp.Service", "CooperaSharp.Service\CooperaSharp.Service.csproj", "{29265864-0214-49D9-8B5A-FDB9C9999133}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{00FA2EFE-BDE3-4E49-BE2B-232693C19A72}"
ProjectSection(SolutionItems) = preProject
compose.yaml = compose.yaml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CooperaSharp.Service.Tests", "CooperaSharp.Service.Tests\CooperaSharp.Service.Tests.csproj", "{3254B12C-1F64-49D3-94B5-7287789CB4F5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{29265864-0214-49D9-8B5A-FDB9C9999133}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29265864-0214-49D9-8B5A-FDB9C9999133}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29265864-0214-49D9-8B5A-FDB9C9999133}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29265864-0214-49D9-8B5A-FDB9C9999133}.Release|Any CPU.Build.0 = Release|Any CPU
{3254B12C-1F64-49D3-94B5-7287789CB4F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3254B12C-1F64-49D3-94B5-7287789CB4F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3254B12C-1F64-49D3-94B5-7287789CB4F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3254B12C-1F64-49D3-94B5-7287789CB4F5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>

<ItemGroup>
<Content Include="..\.dockerignore">
<Link>.dockerignore</Link>
</Content>
</ItemGroup>

</Project>
21 changes: 21 additions & 0 deletions CooperaSharp/CooperaSharp.Service/CooperaSharp.Service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM mcr.microsoft.com/dotnet/runtime:9.0 AS base
USER $APP_UID
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["CooperaSharp.Service/CooperaSharp.Service.csproj", "CooperaSharp.Service/"]
RUN dotnet restore "CooperaSharp.Service/CooperaSharp.Service.csproj"
COPY . .
WORKDIR "/src/CooperaSharp.Service"
RUN dotnet build "./CooperaSharp.Service.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./CooperaSharp.Service.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "CooperaSharp.Service.dll"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace CooperaSharp.Service;

public class PedidoDto
{
public int ClienteId { get; set; }
public string EnderecoEntrega { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace CooperaSharp.Service;

public interface ILogger
{
void Log(string clienteNãoEncontrado);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace CooperaSharp.Service;

public interface IMapper
{
T Map<T>(PedidoDto dto);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace CooperaSharp.Service;

public class Client
{
public string Email { get; set; }
}
Loading