.NET

7 jan, 2016

.NET – Usando Moq em testes unitários – Parte 01

Publicidade

Se é a primeira vez que você ouve os termos “mock”, “objetos mock”, “mocar” e “mocking”,  você vai estranhar e isso é normal, afinal essa palavra ainda não foi incorporada ao seu vocabulário. A partir de hoje, você aprendeu mais uma palavra.

Existe na língua portuguesa o verbo mocar, que significa enganar, atraiçoar ou ainda esconder (popular), mas, na área de software, mocar objetos ou Mock Objects significa objetos que imitam objetos reais para realização de testes de software.

Na programação orientada a objeto, objetos mock ou fictícios são objetos simulados que imitam o comportamento de objetos reais. Os objetos Mocks são geralmente usados em testes unitários.

Assim, os objetos Mock são criados para testar o comportamento de algum outro objeto (real); com isso, estamos mocando, ou seja, simulando ou fingindo o objeto real e fazendo algumas operações de forma controlada, de modo que o resultado retornado (teste) é sempre válido.

Por que devemos usar objetos Mock?

A utilização de objetos Mock está relacionada com os testes unitários e com o Test-Drive Development (TDD), e de forma geral é indicada quando temos um dos seguintes cenários:

  • Os objetos fornecem resultados não determinísticos (ex.: hora, temperatura etc.);
  • Os objetos possuem estados que não são fáceis de criar ou reproduzir (ex.: erro em ambiente de redes etc.);
  • A utilização dos objetos é muito lenta (ex.: banco de dados complexo que deve ser inicializado antes do teste etc.);
  • Os objetos ainda não existem ou podem mudar de comportamento;
  • Para realizar os testes, você teria que incluir informação e métodos exclusivos para os objetos;

Quando temos objetos com essas características, eles são bons candidatos para serem mocados, ou seja, para serem substituídos por objetos que simulam esses comportamentos e que vão nos retornar os resultados que precisamos ou esperamos.

Em geral, existem três tipos de objetos simulados : Mock, Stubs e Fakes.

  • Fakes: – são objetos mais simples que implementam a mesma interface dos objetos que representam e retornam respostas pré-arranjadas. Assim, eles contêm apenas um conjunto de métodos.
  • Mocks: são objetos pré-programados com informações que formam uma especificação das chamadas que esperam receber;
  • Stubs: providenciam respostas pré-configuradas para as chamadas feitas durante os testes; em geral não respondem a nada que não esteja programado para o teste.

Nota: Stubs são usados para representar e testar o estado de um objeto, e os Mocks são usados para testar as suas interações.

Existem muitos frameworks que podemos usar para mocar objetos ou realizar o mocking em nossos projetos na plataforma .NET, e neste artigo eu vou tratar do framework Moq.

O que é Moq?

Moq é uma biblioteca para mocar objetos para a plataforma .NET desenvolvida para tirar o máximo proveito de recursos como Linq, árvores de expressão, expressões lambdas etc.

Assim, ela suporta a mocagem de interfaces bem como classes.

Sua API é extremamente simples e direta, e não requer nenhum conhecimento ou experiência prévia com os conceitos de mocking.

A sua instalação pode se feita via Nuget ou manualmente, como veremos no projeto exemplo.

Recursos usados:

Criando o projeto exemplo no VS 2013 Community

Abra o VS 2013 Community e clique em New Project. A seguir, selecione Visual C# -> Windows Forms Application. Informe o nome Moq_demo e clique no botão OK.

net_mock-1No menu PROJECT, clique em Add Class e informe o nome Socio. A seguir, inclua o código abaixo nessa classe:

public class Socio
{
        public int SocioID { get; set; }
        public string Nome { get; set; }
        public string Sobrenome { get; set; }
        public int Limite { get; set; }
        public int Idade { get; set; }
}

No menu PROJECT, clique em Add New Item e selecione o template Interface informando o nome ISocio. A seguir, inclua o código abaixo nessa interface:

public interface ISocio
 {
        Socio GetSocio(int socioID);
 }

Nessa interface, definimos um método chamado GetSocio(), que obtém um sócio pelo seu código. Esse método deverá ser implementado na classe que usar essa interface.

No nosso exemplo, vamos criar a classe GerenciaSocio() que implementa essa interface.

No menu PROJECT, clique em Add Class e informe o nome GerenciaSocio.

public class GerenciaSocio : ISocio
 {
        public Socio GetSocio(int socioID)
        {
            throw new NotImplementedException();
        }
 }

Não vamos definir nenhuma implementação no método, pois vamos mocar o objeto em nosso projeto teste.

Agora vamos criar uma classe chamada Clube, na qual iremos definir o método CalcularFrete() para calcular o valor do frete devido por cada sócio referente ao envio de material.

No menu PROJECT, clique em Add Class e informe o nome Clube.

Digite o código a seguir nessa classe:

public class Clube
 {
        private readonly ISocio _socio;

        public Clube(ISocio socio)
        {
            this._socio = socio;
        }

        public double CalcularFrete(int socioID)
        {
            double socioValorFrete = 0;
            Socio socio = _socio.GetSocio(socioID);
            socioValorFrete = 10 + socio.Limite * 0.8;
            return socioValorFrete;
        }
 }

O código dessa classe define o método CalcularFrete(), que a partir do código do sócio calcula o valor do frete.

Note que nessa classe usamos o padrão de projeto inversão de controle, e temos assim uma classe com baixo acoplamento.

O que vamos fazer a seguir é realizar a injeção da dependência e podemos injetar qualquer tipo de objeto que é implementado a partir da interface ISocio no construtor da classe.

Dessa forma, já temos um projeto pronto e vamos agora criar o projeto de testes e utilizar o Moq para mocar os objetos e realizar os testes unitários.

net_mock-2

Na segunda parte do artigo, iremos criar o projeto para testes e utilizar o Moq para testar o nosso projeto Moq_demo.