Cuide bem do seu domínio! Parte 2

Dando sequência ao post anterior vamos iniciar os testes de validação das nossas entidades com base nas especificações de Alunos e Matriculas.

Passo 13 - Abra o arquivo AlunoTests.cs no projeto de testes. Na barra de menu do Visual Studio clique em TEST -> RUN -> ALL TESTS. A imagem abaixo mostra o resultado na guia Test Explorer, retornando False na classe onde informamos dados inválidos(Aluno_Consistente_False), e retornando True para a classe onde passamos dados válidos(Aluno_Consistente_True).

Note que se informarmos dados inválidos no método que aguarda um boolean igual a True, o teste não passará. Veja na imagem abaixo.

Portanto, teste sempre as suas entidades sempre esperando retornos true quando as propriedades são válidas e false para propriedades inválidas.

Até aqui validamos e testamos os requisitos de CPF obrigatório e idade entre 6 e 18 anos para cadastro do aluno. Vamos agora testar o segundo requisito da entidade Aluno que exige CPF único na base.

Peraí... como vamos testar CPF único na base se ainda não temos banco de dados ?

Simples uai, basta usar um framework que permita simular uma consulta no banco. Essa é a técnica que chamamos de Mock

Passo 14 - Primeiramente, vamos criar o repositório genérico. Crie uma interface chamada "IRepository" na pasta \Domain\Interfaces\Repository
IRepository.cs

1
2
3
4
5
6
7
8
9
10
public interface IRepository : IDisposable where TEntity : class
{
    TEntity Adicionar(TEntity obj);
    TEntity ObterPorId(Guid id);
    IEnumerable ObterTodos();
    TEntity Atualizar(TEntity obj);
    void Remover(Guid id);
    IEnumerable Buscar(Expression<Func<TEntity, bool>> predicate);
    int SaveChanges();
}

Linha 1 - Estamos restringindo o parâmetro de tipo genérico a um tipo classe
Linha 8 – Busca genérica que recebe uma expressão lambda e percorre as propriedades com base nos filtros informados no parâmetro predicate.

Passo 15 - Vamos especializar o repositório genérico criando interfaces com métodos específicos para cada entidade. Veja o exemplo da interface com método específico para a entidade Aluno que herda os métodos do repositório genérico.
IAlunoRepository.cs

1
2
3
4
public interface IAlunoRepository : IRepository
{
    Aluno ObterPorCpf(string cpf);
}

Passo 16 - Essas interfaces já serão suficientes para validar o CPF único. Crie uma classe de especificação na pasta \Specifications\Alunos\ chamada AlunoCpfUnicoSpecification

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class AlunoCpfUnicoSpecification : ISpecification
{
    private readonly IAlunoRepository _alunoRepository;
 
    public AlunoCpfUnicoSpecifications(IAlunoRepository alunoRepository)
    {
        _alunoRepository = alunoRepository;
    }
 
    public bool IsSatisfiedBy(Aluno aluno)
    {
        return _alunoRepository.ObterPorCpf(aluno.CPF) == null;
    }
}

Linhas 5 a 8 - Percebam que estamos passando instância dos objetos que implementam a interface IAlunoRepository por injeção de dependência.

Passo 16 - Agora vamos criar a classe de validação na pasta \Validations\Alunos\AlunoCadastroValidation.cs que herdará a classe Validator do pacote DomainValidation.

1
2
3
4
5
6
7
8
9
public class AlunoCadastroValidation : Validator
{
    public AlunoCadastroValidation(IAlunoRepository alunoRepository)
    {
        var cpfUnico = new AlunoCpfUnicoSpecification(alunoRepository);
 
        base.Add("cpfUnico", new Rule(cpfUnico, "CPF já cadastrado!"));
    }
}

Passo 17 - Estamos pronto para testar. Antes, vamos instalar o framework Rhino Mocks. Instale no projeto de testes através do comando - Install-Package RhinoMocks

Passo 18 - Vamos criar a classe que valida CPF único. No projeto de teste, crie uma pasta chamada \Validation e adicione a classe AlunoCadastroTest.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class AlunoCadastroTest
{
    public Aluno Aluno { get; set; }
 
    [TestMethod]
    public void Aluno_Consistente_True()
    {
        Aluno = new Aluno()
        {
            CPF = "65560639834"
        };
        var stubRepository = MockRepository.GenerateStub();
        stubRepository.Stub(s => s.ObterPorCpf(Aluno.CPF)).Return(null); // objeto não encontrado - null
 
        var alunoValidation = new AlunoCadastroValidation(stubRepository);
        Assert.IsTrue(alunoValidation.Validate(Aluno).IsValid);
    }
    public void Aluno_Consistente_False()
    {
        Aluno = new Aluno()
        {
            CPF = "65560639834"
        };
        var stubRepository = MockRepository.GenerateStub();
        stubRepository.Stub(s => s.ObterPorCpf(Aluno.CPF)).Return(Aluno); // objeto encontrado
 
        var alunoValidation = new AlunoCadastroValidation(stubRepository);
        Assert.IsFalse(alunoValidation.Validate(Aluno).IsValid);
    }
}

Linhas 8 a 11 - o método cria uma instancia de Aluno atribuindo um CPF.
Na linha 12, criamos um repositório falso "stubRepository" que implementa a interface IAlunoRepository.
Na linha 13, utilizamos o método ObterPorCpf passando o cpf a ser obtido e forçando um retorno null. Podemos retornar qualquer informação aqui. Nesse caso, retornamos null pois estamos validando a especificação que retornaria do banco de dados um valor null quando o cpf não existir.

Na linha 15, a classe AlunoCadastroValidation espera receber qualquer classe que implemente IAlunoRepository e por isso passamos como parâmetro o repositório falso, stubRepository, que implementa a interface esperada pela classe.

Percebam que invertemos o resultado no método Aluno_Consistente_False retornando o próprio Aluno, simulando a existência do CPF obtido pelo método ObterPorCpf do repositório.

Até aqui, a entidade Aluno já está validando todos os requisitos - CPF válido e único na base. E lembrando que ainda não saímos da camada de domínio. Particularmente, eu considero uma boa prática implementar todas as regras de negócio no domínio e testá-las antes de seguir com o desenvolvimento das outras camadas.

No próximo post, vamos fazer a validação das entidades Matrícula e Curso utilizando classes de serviço no domínio.

Até mais!
Thanks for reading!

One thought on “Cuide bem do seu domínio! Parte 2

  1. Cara estou iniciando .Net e apreendendo sobre a estrutura ddd, muito bom esse tutorial, tem sido de bastante ajuda no meu aprendizado, Parabéns é pouco mew velho!!

Leave a Reply

Your email address will not be published. Required fields are marked *

This blog is kept spam free by WP-SpamFree.