Nos testes unitários, podemos simular o comportamento de objetos reais complexos. Principalmente, quando estes objetos são difíceis de serem incorporados nos testes de unidade.

A utilização de mocks elimina a necessidade de utilizar alternativas mais lentas. Por exemplo, banco de dados, que precisam ser inicializados antes da execução dos testes e fornece um feedback muito mais rápido ao desenvolvedor.

Neste post, vou mostrar para vocês alguns exemplos da utilização de mock e como isso pode ser interessante no desenvolvimento!

*Fica a dica: O caso descrito nesse post é inspirado na arquitetura Clean, descrita no livro “Clean Code” – Robert Cecil Martin. Para saber mais acesse este link.

Repositórios

Criamos uma classe mock para cada repositório, contendo um método para instanciar (ou obter uma instância existente, caso seja necessário) da classe e outro para retornar o objeto Mock.

testes unitários

Para cada método a ser implementado criamos, na mesma classe, um método. É possível fazer mais de uma implementação do mesmo método, caso necessário.

testes unitários

No exemplo acima, existe um parâmetro “nome” com valor padrão definido no construtor. Desta forma, quando necessário, podemos passar um valor diferente para manipular o objeto e executar um teste específico. Caso seja necessário manipular muitas propriedades ou até mesmo todo o objeto, é possível passar o objeto inteiro via parâmetro e retorná-lo.

testes unitários

Testes Unitários

Ao obter a instância de um repositório mock, implementamos apenas os métodos que utilizaremos em nossa camada de casos de uso a ser testada, manipulando via parâmetros quando necessário.

Na implementação abaixo, criamos um mock do método ObterPessoa, passando uma data de nascimento X via construtor. Isso significa que, para qualquer chamada ao método ObterPessoa passando qualquer string Y no parâmetro Cpf, iremos retornar um objeto com Cpf = Y, Nome = “Nome Aleatorio” e Nascimento = X.

testes unitários

Na classe OperacoesPessoa, vemos a implementação real do método ObterIdadePessoa.

testes unitários

Nos testes abaixo, chamamos implementamos nosso objeto Mock com duas datas de nascimento diferentes, resultado em dois objetos diferentes do tipo Pessoa.

Portanto, com duas implementações diferentes, podemos testar que nosso método funciona.

testes unitários

Tratar Validações

Ao tratar validações, é muito comum utilizar o atributo ExpectedException no método de teste para testar se uma determinada exceção é lançada. Mas, desta forma, não conseguimos testar se a exceção está sendo lançada onde esperamos que ela seja lançada, a não ser que seja uma exceção tipada. Caso contrário, apenas testamos que aquele tipo de exceção é lançado em algum momento do código.

testes unitários

Como alternativa, ao realizar uma validação, retornamos um erro como propriedade do objeto e damos um assert no código da mesma. Desta forma, conseguimos validar exatamente o trecho de código que estamos esperando um erro.

testes unitarios

Desenvolver testes unitários utilizando mocks faz com que o desenvolvedor pense de forma diferente ao implementar um sistema. Os testes individuais são testados para garantir que operem corretamente. Cada componente é testado independentemente, sem os outros componentes de sistema, o que faz com que estes componentes tenham um baixo acoplamento.

Na dti, a preocupação com testes é constante. Assim podemos garantir a entrega de uma solução mais robusta e confiável para o cliente.