Skip to content

Commit

Permalink
Update Readme
Browse files Browse the repository at this point in the history
  • Loading branch information
DiegoLins10 committed Jun 24, 2024
1 parent 985ce56 commit 7ef88ae
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Para entender os conceitos utilizados neste código em relação a testes unitários, precisamos focar em alguns princípios chave e práticas que facilitam a testabilidade do código. Vou abordar os conceitos principais utilizados neste código e como eles se relacionam com testes unitários.
Para entender os conceitos utilizados neste código em relação a testes unitários precisamos focar em alguns princípios chave e práticas que facilitam a testabilidade do código. Vou abordar os conceitos principais utilizados neste código e como eles se relacionam com testes unitários.

### Conceitos Utilizados no Código

Expand Down
206 changes: 206 additions & 0 deletions README.md.bak
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
Para entender os conceitos utilizados neste código em relação a testes unitários precisamos focar em alguns princípios chave e práticas que facilitam a testabilidade do código. Vou abordar os conceitos principais utilizados neste código e como eles se relacionam com testes unitários.

### Conceitos Utilizados no Código

1. **Injeção de Dependência (Dependency Injection)**:
- **Definição**: É um padrão de design que permite a injeção de dependências (objetos que uma classe precisa para funcionar) em uma classe através do seu construtor ou métodos.
- **No código**: O repositório `IEmployeeRepository` é injetado no construtor da classe `EmployeeService`.

```csharp
public EmployeeService(IEmployeeRepository repository)
{
_repository = repository;
}
```

- **Para testes unitários**: A injeção de dependência facilita a substituição de dependências reais por mocks ou stubs durante os testes, permitindo isolar a unidade de código que está sendo testada.

2. **Interface**:
- **Definição**: Interfaces são contratos que definem quais métodos e propriedades uma classe deve implementar, sem fornecer a implementação real.
- **No código**: `IEmployeeRepository` é uma interface que define o método `Add`.

```csharp
public interface IEmployeeRepository
{
void Add(Employee employee);
}
```

- **Para testes unitários**: O uso de interfaces permite a criação de mocks. Você pode criar uma implementação falsa (`mock`) de `IEmployeeRepository` para testar o comportamento da `EmployeeService` sem interagir com a camada de dados real.

3. **Mocking**:
- **Definição**: É o processo de criação de objetos falsos que imitam o comportamento de objetos reais. Mocks são usados para testar a interação entre unidades de código.
- **Para testes unitários**: Em testes, você pode usar bibliotecas de mocking (como Moq em C#) para criar um mock de `IEmployeeRepository` e verificar se os métodos corretos foram chamados.

### Exemplo de Teste Unitário com Moq

Aqui está um exemplo de como você poderia escrever um teste unitário para o método `Add` da `EmployeeService` usando a biblioteca Moq:

```csharp
using Moq;
using Xunit;
using HrManager.Application.Models.InputModels;
using HrManager.Application.Models.ViewModels;
using HrManager.Application.Services;
using HrManager.Core.Repositories;

public class EmployeeServiceTests
{
[Fact]
public void Add_Should_Call_Repository_Add_And_Return_ViewModel()
{
// Arrange
var mockRepository = new Mock<IEmployeeRepository>();
var service = new EmployeeService(mockRepository.Object);
var inputModel = new AddEmployeeInputModel
{
// Inicialize o modelo de entrada com dados de teste
};
var expectedEmployee = inputModel.ToEntity();

// Act
var result = service.Add(inputModel);

// Assert
mockRepository.Verify(r => r.Add(It.Is<Employee>(e => e == expectedEmployee)), Times.Once);
Assert.NotNull(result);
Assert.IsType<AddEmployeeViewModel>(result);
Assert.Equal(expectedEmployee.Name, result.Name); // Exemplo de verificação de propriedade
}
}
```

### Explicação do Teste Unitário

1. **Arrange**: Configuramos o cenário do teste.
- Criamos um mock de `IEmployeeRepository` usando Moq.
- Criamos uma instância do `EmployeeService` passando o mock do repositório.
- Inicializamos um `AddEmployeeInputModel` com dados de teste.
- Convertemos o modelo de entrada em uma entidade esperada.

2. **Act**: Executamos o método `Add` do `EmployeeService`.

3. **Assert**: Verificamos se o método `Add` do repositório foi chamado uma vez com a entidade esperada.
- Usamos `mockRepository.Verify` para verificar a interação com o mock.
- Checamos se o resultado não é nulo e se é do tipo correto.
- Verificamos propriedades específicas no resultado para garantir que os dados foram processados corretamente.

### Conclusão

O código utiliza injeção de dependência e interfaces para promover a separação de preocupações e facilitar o teste. Isso permite a criação de testes unitários eficazes, onde dependências externas podem ser mockadas para isolar a unidade de código que está sendo testada. O uso de bibliotecas de mocking como Moq facilita a verificação de interações e comportamento do código em testes.

### Tecnologias
- XUnit
- Moq (Mock)
- Auto fixture
- Shouldly


Esse código é um exemplo de testes unitários usando a biblioteca xUnit.net, Moq para criação de mocks, AutoFixture para geração de dados aleatórios e Shouldly para assertivas de teste mais expressivas. Vamos analisar cada parte do código:

### Estrutura Geral

```csharp
using AutoFixture;
using HrManager.Application.Models.InputModels;
using HrManager.Application.Services;
using HrManager.Core.Entities;
using HrManager.Core.Exceptions;
using HrManager.Core.Repositories;
using Moq;
using Shouldly;
using System;
using Xunit;

namespace HrManager.UnitTests.Application.Services.EmployeeServiceTests
{
public class EmployeeServiceAddTests
{
[Fact]
public void ValidEmployee_AddIsCalled_ReturnValidEmployeeViewModel()
{
// Arrange
var addEmploymentInputModel = new Fixture().Create<AddEmployeeInputModel>();

var employeeRepositoryMock = new Mock<IEmployeeRepository>();

var employeeService = new EmployeeService(employeeRepositoryMock.Object);

// Act
var result = employeeService.Add(addEmploymentInputModel);

// Assert
Assert.Equal(addEmploymentInputModel.Role, result.Role);
Assert.Equal(addEmploymentInputModel.FullName, result.FullName);
Assert.Equal(addEmploymentInputModel.Document, result.Document);
Assert.Equal(addEmploymentInputModel.BirthDate, result.BirthDate);
Assert.Equal(addEmploymentInputModel.RoleLevel, result.RoleLevel);
Assert.Equal(addEmploymentInputModel.Role, result.Role);

result.FullName.ShouldBe(addEmploymentInputModel.FullName);
result.Document.ShouldBe(addEmploymentInputModel.Document);
result.BirthDate.ShouldBe(addEmploymentInputModel.BirthDate);
result.RoleLevel.ShouldBe(addEmploymentInputModel.RoleLevel);
result.Role.ShouldBe(addEmploymentInputModel.Role);

employeeRepositoryMock.Verify(er => er.Add(It.IsAny<Employee>()), Times.Once);
}

[Fact]
public void InvalidBirthDateForEmployee_AddIsCalled_ThrowAnInvalidBirthDateException()
{
// Arrange
var addEmploymentInputModel = new Fixture().Create<AddEmployeeInputModel>();
addEmploymentInputModel.BirthDate = DateTime.Today.AddDays(1);

var employeeRepositoryMock = new Mock<IEmployeeRepository>();
var employeeService = new EmployeeService(employeeRepositoryMock.Object);

// Act + Assert
var exception = Assert.Throws<BirthDateCannotBeInTheFutureException>(() =>
employeeService.Add(addEmploymentInputModel));

Assert.Equal("Birth date cannot be in the future.", exception.Message);

Should.Throw<BirthDateCannotBeInTheFutureException>(() =>
employeeService.Add(addEmploymentInputModel))
.Message.ShouldBe("Birth date cannot be in the future.");
}
}
}
```

### Explicação

#### Usings

- **Usings Iniciais**: Importações de namespaces necessários para o teste, incluindo `AutoFixture` para criação de dados aleatórios, definições de modelos (`AddEmployeeInputModel`), serviços (`EmployeeService`), entidades (`Employee`), exceções (`BirthDateCannotBeInTheFutureException`) e repositórios (`IEmployeeRepository`).

#### Namespace e Classe de Teste

- **Namespace `HrManager.UnitTests.Application.Services.EmployeeServiceTests`**: A estrutura do namespace sugere que esses testes estão no contexto de testes para a classe `EmployeeService` no projeto `Application.Services` dentro do projeto `HrManager`.
- **Classe `EmployeeServiceAddTests`**: Classe de testes para testar o método `Add` da classe `EmployeeService`.

#### Métodos de Teste

1. **`ValidEmployee_AddIsCalled_ReturnValidEmployeeViewModel`**:
- **Arrange**: Preparação para o teste. Utiliza o `AutoFixture` para criar um `AddEmployeeInputModel` com dados aleatórios.
- Cria um mock de `IEmployeeRepository` e o injeta no `EmployeeService`.
- Modifica a data de nascimento (`BirthDate`) para garantir que não seja no futuro.
- **Act**: Chama o método `Add` do `EmployeeService` com o modelo de entrada criado.
- **Assert**: Verifica se o método `Add` do repositório foi chamado uma vez com qualquer instância de `Employee`. Compara as propriedades do resultado (`result`) com as propriedades do modelo de entrada (`addEmploymentInputModel`) usando assertivas do xUnit (`Assert.Equal`) e Shouldly (`result.FullName.ShouldBe`, etc.).

2. **`InvalidBirthDateForEmployee_AddIsCalled_ThrowAnInvalidBirthDateException`**:
- **Arrange**: Prepara um `AddEmployeeInputModel` com uma data de nascimento (`BirthDate`) no futuro.
- Cria um mock de `IEmployeeRepository` e o injeta no `EmployeeService`.
- **Act + Assert**: Verifica se chamar o método `Add` do `EmployeeService` com um modelo de entrada inválido resulta em uma exceção do tipo `BirthDateCannotBeInTheFutureException`. Usa assertivas do xUnit (`Assert.Throws`) e Shouldly (`Should.Throw`) para validar a exceção e sua mensagem.

### Considerações Finais

- **Mocking (`Mock<IEmployeeRepository>`)**: Usado para simular o comportamento do repositório de empregados sem realmente acessar o banco de dados.
- **AutoFixture**: Utilizado para criar dados aleatórios, facilitando a preparação de cenários de teste.
- **Assertivas**:
- **xUnit (`Assert.Equal`, `Assert.Throws`)**: Assertivas padrão do xUnit para verificar resultados.
- **Shouldly (`ShouldBe`, `Should.Throw`)**: Lib adicional para assertivas mais expressivas e legíveis.

Este código exemplifica uma abordagem típica de teste unitário em C#, onde cada método de teste é focado em validar um cenário específico e verificar o comportamento esperado da classe `EmployeeService` ao adicionar empregados.

0 comments on commit 7ef88ae

Please sign in to comment.