Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

RSS iMasters

[Resolvido] Como testar e gerar mock de tipos ou membros protect

Recommended Posts

O Rhino Mocks é um framework para geração de mocks, artifício muito utilizado na abordagem de desenvolvimento TDD. Um grande problema é que o Rhino Mocks, ao contrário de frameworks como o Moq, não conseguem ?mockear? métodos e propriedades com modificadores de acesso restrito, como protected e internal. Isso força o desenvolvedor a definir como public todos os tipos e membros implementados, o que acarreta em uma exposição indesejada e mas forçada do que não é verdadeiramente público.

O que fazer?

Existem alguns caminhos a se seguir: mudar de framework, implementar duas interfaces para cada classe (uma com a exposição do que realmente se deve expor para quem irá utilizar a classe e outra com todos os métodos e propriedades expostos, para serem utilizados pelos casos de teste), entre outras formas possíveis. Vou apresentar duas dessas formas neste artigo: mock de modificadores internal e protected.

Algumas definições

  • internal 

 O tipo ou membro internal pode ser acessado por qualquer código implementado no mesmo assembly.

  • protected

O tipo ou membro protected pode ser acessado apenas dentro da classe que ele for implementado ou em classes que especialize a classe que tem o mesmo implementado.

Modificador de acesso: internal

Para exemplificar, de uma forma mais didática, o mock destes dois tipos de modificadores, eu criei um cenário bem simples. Vejamos na pratica:

1. Criei um projeto ?Dominio?:

figura1.png

2. Implementei duas classes :

  • Pedido:
public class Pedido {    public virtual List<Item> itens{get;set;}    public virtual decimal ValorTotal { get; set; }     public Pedido()    {       this.itens = new List<Item>();    }     public virtual void  AdicionarItem(Item item)    {       CalcularTotalDoPedido(item);       this.itens.Add(item);    }     Internal virtual void CalcularTotalDoPedido(Item item)    {       throw new NotImplementedException()    } }
  • Itens:
public class Item {     public virtual Pedido Pedido { get; set; }      public Item()     {      }  }

O código visa incluir um item no pedido e também calcular o seu total. Perceba que foi implementado o método AdicionarItem e que ele é público, já o método CalcularTotalDoPedido é internal e não está implementado.

3. Criei um projeto de testes "Dominio.Testes":

figura2.png

4. Criei uma classe de testes, "Pedido.Testes":

figura3.png

Note que não tenho acesso ao método internal CalcularTotalDoPedido. Normalmente, os casos de teste estão implementados em um outro assembly. Sendo assim, não consigo gerar o mock de alguém que seja internals, porém existe uma brecha para se fazer isso sem muito esforço.

É preciso informar ao assembly que todos os internals serão visíveis para um assembly específico. Existe um arquivo dentro de properties do projeto, chamado AssemblyInfo.cs, conforme a figura:

figura4.png

5. Inclua no final do arquivo o seguinte trecho de código:

 

//Para visibilidade dentro do assembly de testes //Perceba que o assembly é o assembly de testes [assembly: InternalsVisibleTo("Dominio.Testes")]

figura5.png

Se acessarmos o caso de teste implementado, veremos que agora nós temos acesso ao método internal CalcularTotalDoPedido, e sendo assim, podemos fazer o mock do mesmo:

figura6.png

Agora conseguimos mockear e até testar, se for o caso, um método de modificador internal.

Modificador de acesso: protected

Antes de mais nada, preciso explicar o que percebi e que me possibilita mockear ou até mesmo testar algo protegido.

Sabemos por definição que o tipo ou membro protected pode ser acessado somente dentro da classe que ele for implementado ou em classes que especializão a classe que tem o mesmo implementado.

figura7.png

Logo, se "Classe B" especializa a "Classe A", então, a "Classe B" tem acesso na sua implementação a tipos ou membros da "Classe A". O natural é que ambas as instâncias de B e A não exponham o método protegido, como vemos a seguir:

figura8.png

No entanto, se a "Classe B" instancia ela mesma, então, temos acesso a todo conteúdo protected da "Clase A" na instância da "Classe B", ficando assim:

figura9.png

Caso a classe C especialize a classe A:

figura10.png

Obteremos o mesmo resultado quando tentamos instanciar a "Classe B" e acessar métodos protected:

figura11.png

Mas se tentarmos instanciar a "Classe C", nela mesma teremos:

figura12.png

Com isso, conclui-se que, dado uma classe X  que tenha tipos e membros protected e instancie a si mesma em um objeto x, o objeto x irá expor todos os tipos ou membros. Isso nos possibilita gerar um mock e testar.

Vamos aproveitar o mesmo cenário, porém trabalhando com o modificador protected.

 

O método da classe Pedido CalcularTotalDoPedido agora será protected, o que piorou a história, pois preciso fazer um mock dele e não tenho acesso.

Vamos recordar como funciona o modificador protected:

Visto que uma classe especialista (herança) da classe Pedido tem acesso aos tipos ou métodos protected, temos um caminho para fazermos o teste de Pedidos:

figura13.png

A classe PedidoTestes irá especializar Pedido. Ok, mas e daí? Perceba que isso possibilita testar a classe Pedidos indiretamente. O código vai ficar assim:

figura14.png

Veja que ao invés de mockear o pedido, tendo ele como alvo direto, eu faço o mock de PedidoTestes:

var pedido = repositorioMock.PartialMock<PedidoTestes>();

E em seguida eu gero uma expectativa para CalcularTotalDoPedido que é protegida na implementação real.

pedido.Expect(p => p.CalcularTotalDoPedido(null)).IgnoreArguments();

Rodando o teste:

figura15.png

Acessando um serviço que consumiria a classe Pedido, vemos que o método Calcular CalcularTotalDoPedido não é visível.

figura16.png

Vimos a possibilidade de gerar mock de tipos ou membros internal e protected apenas com os recursos de orientação a objetos e do .Net. Sendo assim, você pode continuar usando o framework Rhino Mocks ou qualquer outro que você já usa sem poluir sua modelagem com um emaranhado de coisas públicas sem a real necessidade.

Até mais!

 

http://imasters.com.br/artigo/24305/dotnet/como-testar-e--gerar-mock-de-tipos-ou-membros-protected-e-internal

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.