O que é Mock em Teste Unitário?

O que é Mock?

Como mockar uma classe em C# .NET ?

Mock é uma técnica para simular o comportamento de estruturas de programação. A utilização desta técnica é fundamental para a validação do layout do código sem afetar ou depender o ambiente em questão.O termo Mock vem do ingles e significa algo como imitação, zombaria, falsidade.

Os testes unitários têm a responsabilidade de garantir que os retornos dos métodos estejam de acordo com as expectativas.Os testes unitários não podem depender da rede estar ativa, ou pastas de rede, servidores ou quaisquer outras dependencias externas. Os testes de integração são responsáveis por testar tais características do ambiente.

Quando existe a necessidade de testar unitáriamente um método que realize uma tarefa que dependa de algum recurso externo é necessário o uso de um Mock. É comum utilizar o neologismo mockar (“…é necessário mockar esta classe”).

A seguir pode-se ver um exemplo de classe. Este exemplo refere-se ao código de uma aplicação que guarda um arquivo texto em um local temporário da maquina. A classe Archiver implementa a interface IArchiver. Ela é especialmente útil para que seja possível mockar esta classe.

namespace Anselme.Mock
{
    public class Archiver : Anselme.Mock.IArchiver
    {
        public ArchiverState Save(string filename, string file)
        {

            string path = System.IO.Path.GetTempPath();
            string completeFileName = string.Concat(path,filename);
            using (System.IO.StreamWriter sw = new System.IO.StreamWriter(completeFileName))
            {
                sw.Write(file);
            }
            return ArchiverState.Saved;
        }

        public string Load(string filename)
        {

            string path = System.IO.Path.GetTempPath();
            string completeFileName = string.Concat(path, filename);
            using (System.IO.StreamReader sr = new System.IO.StreamReader(completeFileName))
            {
                return sr.ReadToEnd();
            }
        }

    }
}

A inteface IArchiver, como eu disse, é um requisito para que eu possa testar unitariamente esta classe com Mock. A seguir, veja o código dela.

namespace Anselme.Mock
{
    public interface IArchiver
    {
        string Load(string filename);
        ArchiverState Save(string filename, string file);
    }
}

Note que o método Save possui um retorno do tipo ArchiverState. Este ArchiverState é uma Enumeração. Ela foi utilizada intensionalmente para gerar algum retorno nesta classe para que ela possa ser testada unitariamente sem a necessidade de verificar se o arquivo está armazenado no disco. Segue o código da enumeracao ArchiverState.

namespace Anselme.Mock
{
    public enum ArchiverState
    {
        Saved
    }
}

O que é MOQ?

Existem vários frameworks para auxiliar na criação de simulações de classes, ou mock. Estes frameworks são de empresas ou grupos independentes. Este tópico utiliza o Framework MOQ que é de simples utilização, bastante eficiente e gratuíto.
O moq possui estruturas para você simular alguma classe por meio da interface que a classe implementa. Com este framework é possível, por exemplo, configurar uma estrutura para que, toda vez que um determinado cenário for criado, um determinado retorno ocorra.
O framework moq pode ser baixado no link: MOQ Framework. Este tópico é feito com base na versão Moq.4.0.10827.Final, Checksum: c9626fcdd253c5a6e33056a2670911b6340cc302

 

Como funciona o Teste unitário com Mock, utilizando o Framework MOQ?

Para ver detalhes sobre como criar um teste unitário veja o link: O que é teste unitário? 
 
O teste unitário a seguir utiliza o Framework MOQ. Ele mostra um exemplo simples de teste do método Save, visto no código do inicio do post.
namespace ArchiverTest
{
    [TestClass()]
    public class ArchiverTest
    {
        [TestMethod()]
        public void Salvando_Um_Arquivo_Com_Texto_Pequeno()
        {

            string filename = string.Format(“{0}.{1}”,TestUtil.CreateRandomString(5), TestUtil.CreateRandomString(3));
            string file = TestUtil.CreateRandomString(5);

            var target = new Mock();
            target.Setup(t => t.Save(filename, file))
                .Returns(ArchiverState.Saved);

            IArchiver target_mock = target.Object;
            ArchiverState state = target_mock.Save(filename, file);
            Assert.AreEqual(ArchiverState.Saved, state);
        }

     }
}

Principais linhas comentadas

var target = new Mock();
Cria-se o Mock da interface IArchiver. Com isto é possível simular os método, propriedade e eventos contidos na interface.
target.Setup(t => t.Save(filename, file))
                .Returns(ArchiverState.Saved);
Com isto, toda vez que se chamar o método Save seu retorno será  ArchiverState.Saved, como já implementado.
IArchiver target_mock = target.Object;
Cria-se um Archiver mockado.
ArchiverState state = target_mock.Save(filename, file);
Obtem-se o resultado do método Save, já configurado.
Assert.AreEqual(ArchiverState.Saved, state);
Verificação se o retorno é o esperado.

Thiago Anselme
Thiago Anselme - Gerente de TI - Arquiteto de Soluções

Ele atua/atuou como Dev Full Stack C# .NET / Angular / Kubernetes e afins. Ele possui certificações Microsoft MCTS (6x), MCPD em Web, ITIL v3 e CKAD (Kubernetes) . Thiago é apaixonado por tecnologia, entusiasta de TI desde a infância bem como amante de aprendizado contínuo.

0 comentário em “O que é Mock em Teste Unitário?

Deixe um comentário