Testes Unitários utilizando Mock: como realizar?

Por Rafael Abdala|
Atualizado: Jul 2023 |
Publicado: Jul 2018

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.
Caso queria realizar testes unitários em Angular no VSTS + SonarQube, acesse este link

Repositórios Mock

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.

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.

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.

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.

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.

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.

Quer ver mais conteúdos como esse?

Testes Unitários utilizando Mock

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.

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.

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

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

Nos testes abaixo, 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.

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

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.

é 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.

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.

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.

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.

Quer saber mais?

Desenvolvimento de Software

Confira outros artigos

Veja outros artigos de Desenvolvimento de Software