Teste Unitários em Projetos SharePoint Utilizando o Padrão Repositório e a biblioteca Moq

Testar projetos SharePoint algumas vezes pode ser um desafio, principalmente por causa dos dados estarem armazenados no SharePoint e para executar os testes eles devem ser executados diretamente de dentro do servidor.

Para esse tipo de problema existem uma solução que consiste em substituir a camada de acesso a dados, no caso fazer um mock, e testar as regras de negócio sem precisar do SharePoint.

Neste post vou mostrar um exemplo de como fazer um mock utilizando a biblioteca Moq com o padrão repostitório para executar os testes unitários nas regras de negócio.

Entidade

Neste case vamos fazer algo bem simples, onde existirá uma entidade chamada pessoa, algumas propriedades e um método de negócio, que é bem simples e só concatena as propriedades, a listagem 01 mostra o código da classe Pessoa.

public class Pessoa
{
    public int ID { get; set; }
    public string Nome { get; set; }
    public DateTime DataNascimento { get; set; }
    public string Endereco { get; set; }
    public int Idade
    {
        get
        {
            return (int) DateTime.Now.Subtract(DataNascimento).TotalDays / 365;
        }
    }

    public string ConcatenarDadosUsuario()
    {
        return string.Format(“ID: {0}, Nome: {1}, Idade: {2}, Endereço: {3}”, this.ID.ToString(), this.Nome, this.Idade.ToString(), this.Endereco);
    }
}

Listagem 01: Implementação da classe pessoa

Repositório

Utilizando o padrão repositório todos os métodos de acesso a dados ficam na classe repositório, facilidando a sua substituição na hora do teste. O primeiro passo é construir a interface, conforme a listagem 02, depois implementar a classe que irá acessar o SharePoint para trabalhar com os dados. Por não haver necessidade, a classe que implementa a interface do repositório não foi implementada, apenas criadas com os métodos padrão. Em um ambiente real ela precisa ser implementada e é a partir dela que todo o acesso ao SharePoint é feito.

public interface IRepositorioPessoas
{

    Pessoa ObterPorID(int pessoaID);

    List<Pessoa> ObterTodos();

    List<Pessoa> ObterPorFiltro(string nome);

    Pessoa Salvar(Pessoa pessoa);

    bool Excluir(int ID);
}

Listagem 02: A interface seguindo padrão repositório

public class RepositorioPessoa: IRepositorioPessoas
{
    public Pessoa ObterPorID(int pessoaID)
    {
        throw new NotImplementedException();
    }

    public List<Pessoa> ObterTodos()
    {
        throw new NotImplementedException();
    }

    public List<Pessoa> ObterPorFiltro(string nome)
    {
        throw new NotImplementedException();
    }

    public Pessoa Salvar(Pessoa pessoa)
    {
        throw new NotImplementedException();
    }

    public bool Excluir(int ID)
    {
        throw new NotImplementedException();
    }
}

Listagem 03: Classe que trabalhar com os dados do SharePoint e implementa a inteface da listagem 02

Teste

A classe de teste é uma classe de teste unitário do Visual Studio, além da implementação feita na listagem 03 é necessário por a referência no projeto a biblioteca Moq (using Moq), que pode ser baixada diretamente pelo Visual Studio através do NuGet Packages (ou pelo site do Moq).

A implementação da classe de teste é um pouco diferente de um testes normal, a primeira coisa a ser feita, na criação da classe de teste é criar o objeto moq para simular a nossa classe de negócio. Todos os dados e regras dos métodos serão implementados neste momento, veja o construtor PessoaTeste, onde um repositório de dados é montado e os métodos implementados. Vejam que é implementação do método mesmo, com as regras sobre os dados recém criados.

A partir do momento que todas as interações com os dados estão feitas, os testes podem ser criados e executados. Como as regras de negócio ficam em outra camada, é simples obter os dados fake e passar para eles e depois obter o resultado, possibilitando assim o teste das regras mesmo sem ter o repositório de dados oficial, no caso o SharePoint.

[TestClass]
public class PessoaTest
{
    public readonly IRepositorioPessoas MockRepositorioPessoa;

    public PessoaTest()
    {
        List<Pessoa> pessoas = new List<Pessoa>
            {
               new Pessoa {ID = 1, Nome = “Pedro de Lara”, Endereco = “Rua Sem Nome, Nr 1″, DataNascimento = new DateTime(1990, 01, 01)},
               new Pessoa {ID = 2, Nome = “Carlos Lara da Silva”, Endereco = “Rua Sem Nome, Nr 2″, DataNascimento = new DateTime(1980, 12, 23)},
               new Pessoa {ID = 3, Nome = “João Cunha”, Endereco = “Rua Sem Nome, Nr 3″, DataNascimento = new DateTime(1989, 02, 02)

            }
    };

    // Criação do Mock utilizando Moq
    Mock<IRepositorioPessoas> mockProductRepository = new Mock<IRepositorioPessoas>();

    // Nas linhas abaixo os métodos estão sendo configurados no mock

    // Retorna todas as pessoas
    mockProductRepository.Setup(mr => mr.ObterTodos()).Returns(pessoas);

    // Retorna a pessoa pelo ID
    mockProductRepository.Setup(mr => mr.ObterPorID(
        It.IsAny<int>())).Returns((int i) => pessoas.Where(
        p => p.ID == i).Single());

    // Retorna as pessoas pelo filtro do nome
    mockProductRepository.Setup(mr => mr.ObterPorFiltro(
        It.IsAny<string>())).Returns((string i) => pessoas.Where(
        p => p.Nome.Contains(i)).ToList());

    // Exclui a pessoa com ID passado por parâmetro
    mockProductRepository.Setup(mr => mr.Excluir(It.IsAny<int>())).Returns(
        (int id) =>
        {
            Pessoa pessoa = pessoas.Where(p => p.ID == id).Single();
            pessoas.Remove(pessoa);

            return true;
        });

    // Salva (insere ou altera) uma pessoa
    mockProductRepository.Setup(mr => mr.Salvar(It.IsAny<Pessoa>())).Returns(
        (Pessoa pessoa) =>
        {
            DateTime now = DateTime.Now;

            if (pessoa.ID.Equals(default(int)))
            {
                // Insere a pessoa nova
                pessoa.ID  = pessoas.Count() + 1;
                pessoas.Add(pessoa);

                return pessoa;
            }
            else
            {
                // Atualiza a pessoa existente
                var original = pessoas.Where(
                    q => q.ID == pessoa.ID).Single();

                if (original == null)
                {
                    return null;
                }

                original.Nome = pessoa.Nome;
                original.Endereco = pessoa.Endereco;
                original.DataNascimento = pessoa.DataNascimento;

                return original;
            }
        });

        // Finaliza a configuração do mock
        this.MockRepositorioPessoa = mockProductRepository.Object;
    }

    /// <summary>
    /// Verifica se todos as pessoas foram retornadas
    /// </summary>
    [TestMethod]
    public void PodeRetornarTodasPessoas()
    {
        // Obtém todas as pessoas
        IList<Pessoa> pessoas = this.MockRepositorioPessoa.ObterTodos();

        Assert.IsNotNull(pessoas); // Teste se é nulo
        Assert.AreEqual(3, pessoas.Count); // Verifica o número de pessoas retornadas
    }

    /// <summary>
    /// Verifica se todos se a pessoa foi retornada a partir do ID
    /// </summary>
    [TestMethod]
    public void PodeRetornarPessoaPorID()
    {
        // Obtém a pessoa com ID 1
        Pessoa pessoa = this.MockRepositorioPessoa.ObterPorID(1);

        Assert.IsNotNull(pessoa); // Teste se é nulo
        Assert.AreEqual(1, pessoa.ID); // Verifica a pessoa retornada é a correta
    }

    /// <summary>
    /// Verifica se todos as pessoas foram retornadas pelo filtro
    /// </summary>
    [TestMethod]
    public void PodeRetornarObterPorFiltro()
    {
        string nome = “Lara”;

        // Obtém a pessoa com ID 1
List<Pessoa> pessoas = this.MockRepositorioPessoa.ObterPorFiltro(nome);

        Assert.IsNotNull(pessoas); // Teste se é nulo
        Assert.AreEqual(2, pessoas.Count); // Verifica a pessoa retornada é a correta
        Assert.AreEqual(true, pessoas[0].Nome.Contains(nome)); // Verifica a pessoa retornada é a correta
        Assert.AreEqual(true, pessoas[1].Nome.Contains(nome)); // Verifica a pessoa retornada é a correta
    }

    /// <summary>
    /// Verifica se a pessoa pode ser inserida
    /// </summary>
    [TestMethod]
    public void PodeInserir()
    {
        Pessoa pessoa = new Pessoa();
        pessoa.Nome = “Pessoa da Silva”;
        pessoa.Endereco = “Rua com Nome 123, nr 12, CEP 34032-000″;
        pessoa.DataNascimento = new DateTime(1979, 12, 21);

        int contador = this.MockRepositorioPessoa.ObterTodos().Count;

        // Salva a pessoa
        pessoa = this.MockRepositorioPessoa.Salvar(pessoa);

        Assert.IsNotNull(pessoa); // Teste se é nulo
        Assert.AreEqual(pessoa.ID, contador + 1);
    }

    /// <summary>
    /// Verifica se a pessoa pode ser alterada
    /// </summary>
    [TestMethod]
    public void PodeAlterar()
    {
        Pessoa pessoa = new Pessoa();
        int id = 1;
        pessoa.ID = id;
        string nome = “Pessoa da Silva”;
        pessoa.Nome = nome;
        pessoa.Endereco = “Rua com Nome 123, nr 12, CEP 34032-000″;
        pessoa.DataNascimento = new DateTime(1979, 12, 21);

        int contador = this.MockRepositorioPessoa.ObterTodos().Count;

        // Salva a pessoa
        pessoa = this.MockRepositorioPessoa.Salvar(pessoa);

        Assert.IsNotNull(pessoa); // Teste se é nulo
        Assert.AreEqual(pessoa.ID, id);
        Assert.AreEqual(pessoa.Nome, nome);
    }

    /// <summary>
    /// Verifica se todos as pessoas foram retornadas
    /// </summary>
    [TestMethod]
    public void PodeExcluir()
    {
        int id = 3;

        // Obtém a pessoa com ID 1
        bool excluido = this.MockRepositorioPessoa.Excluir(id);

        Assert.AreEqual(true, excluido);
    }

    /// <summary>
    /// Verifica se todos as pessoas foram retornadas
    /// </summary>
    [TestMethod]
    public void PodeConcacentarDadosUsuario()
    {
        Pessoa pessoa = this.MockRepositorioPessoa.ObterPorID(2);

        string dadosUsuario = pessoa.ConcatenarDadosUsuario();
        string dadosUsuarioCalculado = string.Format(“ID: {0}, Nome: {1}, Idade: {2}, Endereço: {3}”, pessoa.ID.ToString(), pessoa.Nome, pessoa.Idade.ToString(), pessoa.Endereco);

        Assert.AreEqual(dadosUsuario, dadosUsuarioCalculado);
    }
}

Listagem 03: Implementação do teste unitário

O código-fonte está disponível no GitHub: Testes-Unitarios-SharePoint

About these ads

2 Respostas to “Teste Unitários em Projetos SharePoint Utilizando o Padrão Repositório e a biblioteca Moq”

  1. hantunes Says:

    Muito bom. Obrigado

  2. hantunes Says:

    Muito Bom. Tks


Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

Junte-se a 39 outros seguidores

%d blogueiros gostam disto: