Arquivo | Ferramentas RSS feed for this section

IslandUnit, uma ferramenta que facilita isolamento em testes de unidade

11 mar

Pessoal,

Tenho falado bastante aqui sobre testes de unidade na plataforma .Net. Falei sobre injeção de dependência (Veja: Parte 1 e Parte 2), sobre o NBuilder e sobre como usar o Moq e o NBuilder em nossos testes de unidade.

Foi liberada uma versão beta do IslandUnit, uma ferramenta Open Source que auxilia na utilização dessas várias ferramentas que usamos para fazer isolamento nos testes de unidade.

Com uma interface fluente bem simples de usar, facilita a utilização de frameworks consagrados no mercado, como Moq, Ninject, NBuilder, entre outros.

Vale a pena dar uma olhada! Veja com é simples de usar no Quick Start Guide e depois veja funcionando em um exemplo.

Ah! Ia me esquecendo… O IslandUnit já está disponível no Nuget.

Além de absolutamente indispensável, escrever testes de unidade está ficando cada vez mais divertido! Logo, logo vou fazer um post demonstrando o IslandUnit junto com o Sharp Tests Ex, que também é muito legal.

Forte abraço.

Criando stub’s com Moq e NBuilder para testes de unidade

14 fev

Pessoal,

Recentemente falei sobre injeção de dependência (Veja: Parte 1 e Parte 2), de modo a minimizarmos o acoplamento nas nossas aplicações, onde usamos o Ninject como container de Inversão de Controle (IoC – Inversion of Control) e aproveitamos para apresentar o NuGet.

Também falei recentemente sobre o NBuilder, que nos ajuda a criar objetos fake, para usarmos nos nossos testes de unidade.

A idéia agora é mostrar como criar stub’s para utilizarmos nos nossos testes de unidade. Para isso, usamos algum framework de isolamento (Moq, NMock, Rhino Mocks, TypeMock, etc…). Para quem não sabe o que é um stub, ou acha que stub e mock é tudo a mesma coisa, recomendo fortemente a leitura do artigo: Mocks não são Stubs, do Martin Fowler.

Mas porque precisamos de um stub?
Dizemos que um teste não é um teste de unidade se:

  • Ele se conecta a um banco de dados;
  • Ele se comunica pela rede;
  • Ele “toca” o sistema de arquivos;
  • Ele não pode rodar junto com algum outro dos seus testes de unidade.

Assim, na prática, usamos mock‘s e stub‘s para “simular” acesso a bancos de dados, comunicação via rede, acesso ao sistemas arquivos, etc… Com isso, dizemos que estamos isolando o sistema que está sendo testado.

Vamos ao código?
Como sempre, vamos direto ao assunto, normalmente é mais fácil de entender a idéia. Vamos utilizar o mesmo exemplo dos post’s citados acima:

Interface:

public Interface ICategoryRepository
{
   IList GetAll();
}

Repositório “verdadeiro”:

public class CategoryRepository : ICategoryRepository
{
   public IList GetAll()
   {
      DataContext ctx = new DataContext();
      return ctx.Categories;
   }
}

Repositório “fake”:

public class CategoryRepositoryFake : ICategoryRepository
{
   public IList GetAll()
   {
      var category1 = new Category() { Id = 1, Name = "Cat 1" };
      var category2 = new Category() { Id = 2, Name = "Cat 2" };
      var category3 = new Category() { Id = 3, Name = "Cat 3" };

      return new List() { category1, category2, category3 };
   }
}

Controller:

public class CategoryController : Controller
{
   [Inject]
   public ICategoryRepository Repository { get; set; }

   public ActionResult Index()
   {
      var categories = this.Repository.GetAll();

      return View(categories);
   }
}

A nossa motivação agora é eliminar a classe “CategoryRepositoryFake”. Para isso, utilizaremos o Moq que, dada uma interface (no nosso caso “ICategoryRepository”), ele nos “entrega” um objeto fake automaticamente. Na verdade, ele cria um objeto proxy, cuja finalidade é a de “fingir” ser um objeto “real”, para que um outro componente (ou objeto) possa “acreditar” que está falando com um objeto “real”. Basicamente, a mesma coisa que fizemos quando criamos manualmente o objeto fake… Só que o Moq faz isso de forma transparente e automática, e de quebra nos traz uma série de outros benefícios (coisa pra outro post, em breve).

Vamos ver como ficaria um teste de unidade da action “Index”, usando o Moq, NBuilder e o Ninject. Toda a “brincadeira” é feita na seção “Arrange” do teste:

[TestClass()]
public class CategoryControllerTest
{
   private IKernel kernel = new StandardKernel();

   [TestMethod()]
   public void Index_Returns_List_Of_Categories()
   {
      // Arrange
      // Cria o mock usando o Moq
      Mock<ICategoryRepository> categoryRepositoryMock
                                        = new Mock<ICategoryRepository>();

      // Cria dados "fake" com o NBuilder
      IEnumerable<Category> categoriesList
                         = Builder<Category>.CreateListOfSize(10).Build();

      // Faz o setup do mock usad pelo SUT, para retornar os dados
      // criados com o NBuilder. Acabamos de criar um STUB.
      categoryRepositoryMock
                          .Setup(m => m.GetAll()).Returns(categoriesList);

      // Informamos ao Ninject: Quando alguém precisar de um
      // ICategoryRepository, entregue o objeto criado pelo mock
      kernel.Bind<ICategoryRepository>()
                            .ToMethod(m => categoryRepositoryMock.Object);

      // Act
      CategoryController sut = kernel.Get<CategoryController>();
      ViewResult viewResult = sut.Index();

      // Assert
      IEnumerable<Category> viewData
                     = viewResult.ViewData.Model as IEnumerable<Category>;

      Assert.IsNotNull(viewData);
      Assert.AreEqual(10, viewData.Count());
   }
}

Algumas observações:
Nas linhas 11 e 12, estamos efetivamente criando o nosso objeto mock, baseado na interface “ICategoryRepository”.

Nas linhas 20 e 21, estamos configurando o mock para que, quando alguém invocar o método “GetAll()” do mock, “forçamos” o retorno de uma lista de objetos criada anteriormente, em memória. Acabamos de definir o “tal” stub.

Outro ponto importante está na linha 26. Repare que estamos adicionando ao Ninject uma referência para a interface “ICategoryRepository” apontando para a propriedade “Object” do nosso mock. A propriedade “Object” nos retorna o objeto proxy que comentei anteriormente, e que implementa a interface “ICategoryRepository”.

O que acharam? Nesse post, vimos como criar stub‘s. No próximo, vamos criar mock‘s.

Forte abraço.

Configurando DI em aplicações ASP.NET MVC 3 com Ninject usando NuGet – Parte 2

20 dez

Pessoal,

Na primeira parte desse post, procurei demonstrar de forma mais simples possível uma situação onde seria interessantes aplicarmos o pattern Dependency Injection.

O foco deste post é demonstrar como é fácil fazer a configuração do Ninject em uma aplicação ASP.NET MVC 3, graças à Interface IDependencyResolver e à classe DependencyResolver, mas principalmente pelo NuGet, que são novidades lançadas junto ao ASP.NET MVC 3. Caso você também não conheça o NuGet, existem muitas informações a respeito por aí. Mais uma vez, não vou entrar em detalhes sobre o NuGet aqui, vou somente indicar algumas referências:

http://nuget.codeplex.com
http://haacked.com
http://www.hanselman.com

Somente relembrando do exemplo utilizado na primeira parte:

Interface:

public Interface ICategoryRepository
{
   IList GetAll();
}

Repositório “verdadeiro”:

public class CategoryRepository : ICategoryRepository
{
   public IList GetAll()
   {
      DataContext ctx = new DataContext();
      return ctx.Categories;
   }
}

Repositório “fake”:

public class CategoryRepositoryFake : ICategoryRepository
{
   public IList GetAll()
   {
      var category1 = new Category() { Id = 1, Name = "Cat 1" };
      var category2 = new Category() { Id = 2, Name = "Cat 2" };
      var category3 = new Category() { Id = 3, Name = "Cat 3" };

      return new List() { category1, category2, category3 };
   }
}

Controller:

 public class StoreController : Controller
{
   ICategoryRepository categoryRepository;

   public StoreController() : this(new CategoryRepository())
   {
   }

   public StoreController(ICategoryRepository repository)
   {
      this.categoryRepository = repository;
   }

   public ActionResult Index()
   {
      var categories = this.categoryRepository.GetAll();

      return View(categories);
   }
}

Como dito no outro post, isso funciona, mas temos alguns problemas. Imagine a situação de utilizarmos vários repositórios no nosso Controller… Teríamos que ter vários parâmetros no nosso construtor. Além disso, ainda temos um dependência “incômoda” do construtor sem parâmetros com a implementação do repositório “verdadeiro”.

O que fazer então? É aí que entram os containeres de IoC (Inversion of Control). Eles ficam “esperando” que “alguém peça” algum objeto de determinado tipo, e então se encarregam de instanciar e disponibilizar o objeto para nós, provendo o objeto com todas as suas dependências. Confuso? Vamos ver como fazer isso na prática, usando o container Ninject.

Primeiramente, vamos incluir o Ninject no nosso projeto, utilizando o NuGet. Simples, muito simples:

Abra o NuGet (View > Other Windows > Package Manager Console):

Tela inicial do NuGet

Liste os pacotes disponíveis no repositório oficial do NuGet:

Comando para listar os packages disponíveis

Lista de packages disponíveis, destaque para o Ninject e o Ninject.MVC3

Instale o pacote Ninject.MVC3, que é um wrapper da interface IDependencyResolver para o Ninject. O próprio Ninject será instalado junto, pois trata-se de uma dependência do Ninject.MVC3:

Comando para instalar o Ninject.MVC3, e a mensagem de sucesso, listando todas as dependências instaladas

As referências aos assemblies Ninject e Ninject.MVC3 adicionadas ao projeto

O próximo passo é “informar” ao Ninject quais classes ele deverá instanciar quando lhe for “solicitado” uma instância de determinada Interface. No nosso caso, queremos que o Ninject instancie o ICategoryRepository pra gente. Assim, primeiro vamos remover os construtores do Controller e decorar a propriedade “Repository” com o atributo Inject (linha 3):

public class StoreController : Controller
{
   [Inject]
   public ICategoryRepository Repository { get; set; }

   public ActionResult Index()
   {
      var categories = this.Repository.GetAll();

      return View(categories);
   }
}

O atributo Inject é o responsável por informar ao Ninject que o elemento decorado deve ser instanciado por ele (pode ser um campo, uma propriedade, o parâmetro de um método, entre outros. Veja mais sobre esse atributo aqui).

Em seguida configuramos o Ninject. Para isso, o Ninject.MVC3 cria no diretório raiz da aplicação uma classe chamada AppStart_NinjectMVC3

Classe adicionada ao projeto para configuração do Ninject

… que possui um método chamado RegisterServices. É exatamente esse método que utilizamos para fazer a tal “configuração” do Ninject:

public static void RegisterServices(IKernel kernel) {
   kernel.Bind(ICategoryRepository).To(CategoryRepository);
}

No exemplo acima, estamos informando ao Ninject para, sempre que ele “encontrar” algum elemento cujo tipo seja a Interface ICategoryRepository decorado com o atributo Inject, o container deverá instanciar um CategoryRepository e atribuí-lo a esse elemento.

Uma vez feito isso, no nosso exemplo quando o framework ASP.NET MVC instanciar o seu Controller, “magicamente” a propriedade “Repository” do mesmo estará devidamente instanciada, removendo totalmente a dependência do Controller das implementações de ICategoryRepository.

Forte abraço.

Configurando DI em aplicações ASP.NET MVC 3 com Ninject usando NuGet – Parte 1

8 dez

Pessoal,

Esse é a primeira parte (de dois) desse post. Nessa parte, tentarei falar de forma mais simples e direta possível sobre o pattern injeção de dependência (DI – Dependency Injection). Na segunda parte, mostrarei como configurar e utilizar um container de IoC (Inversion of Control) em uma aplicação ASP.NET MVC 3, utilizando o NuGet.

Para quem não conhece DI, não vou entrar em detalhes conceituais aqui, pois existe muita referência na internet, vou somente recomendar algumas:

Inversion of Control Containers and the Dependency Injection pattern (Martin Fowler)
Wikipedia
Design Patterns: Dependency Injection (MSDN)
Dependency Injection for Loose Coupling

Sendo assim, vamos ver exemplos práticos. Supondo que temos o seguinte código:

Repositório:

public class CategoryRepository
{
   public IList<Category> GetAll()
   {
      DataContext ctx = new DataContext();
      return ctx.Categories;
   }
}

Controller:

public class StoreController : Controller
{
   public ActionResult Index()
   {
      CategoryRepository categoryRepository = new CategoryRepository();
      IList<Category> categories = categoryRepository.GetAll();

      return View(categories);
   }
}

Veja que na linha 5 nós estamos instanciando um CategoryRepository, que acaba nos deixando com um forte acoplamento entre o Controller e o CategoryRepository.

Por isso que, se formos implementar os testes de unidade deste Controller, precisamos criar um Stub desse repositório (uma espécie de repositório “fake”), para que os nossos testes de unidade não precisem se conectar ao banco de dados efetivamente. Assim, quando estivermos executando o teste de unidade desse Controller, vamos precisar “trocar” o repositório CategoryRepository por um repositório que nos retorne um conjunto de dados “fake”, como por exemplo um CategoryRepositoryMock.

Para fazer essa “troca” de repositórios, em primeiro lugar criamos uma interface para o nosso repositório, de modo que tanto o repositório “verdadeiro” quanto o repositório “fake” implementem essa interface, e o nosso Controller terá uma referência para essa interface, e não para os repositórios em si:

Interface:

public Interface ICategoryRepository
{
   IList<Category> GetAll();
}

Repositório “verdadeiro”:

public class CategoryRepository : ICategoryRepository
{
   public IList<Category> GetAll()
   {
      DataContext ctx = new DataContext();
      return ctx.Categories;
   }
}

Repositório “fake”:

public class CategoryRepositoryFake : ICategoryRepository
{
   public IList GetAll()
   {
      Category category1 = new Category() { Id = 1, Name = "Cat 1" };
      Category category2 = new Category() { Id = 2, Name = "Cat 2" };
      Category category3 = new Category() { Id = 3, Name = "Cat 3" };

      return new List<Category>() { category1, category2, category3 };
   }
}

Controller:

public class StoreController : Controller
{
   ICategoryRepository categoryRepository;

   public StoreController() : this(new CategoryRepository())
   {
   }

   public StoreController(ICategoryRepository repository)
   {
      this.categoryRepository = repository;
   }

   public ActionResult Index()
   {
      IList<Category> categories = this.categoryRepository.GetAll();

      return View(categories);
   }
}

Veja que criamos no Controller dois construtores. O primeiro deles não recebe nenhum parâmetro, enquanto o outro recebe por parâmetro um objeto que implemente a interface ICategoryRepository, que executa o outro construtor passando o repositório “verdadeiro”. É esse construtor sem parâmetros que é chamado pelo framework ASP.NET MVC ao instanciar o Controller. Nos nossos testes de unidade, usaremos o segundo construtor para que possamos passar o repositório “fake” para o Controller:

Teste de unidade:

public class StoreControllerTests
{
   [TestMethod]   
   public void Index_Test()
   {
      // Arrange
      ICategoryRepository categoryRepository
                                            = new CategoryRepositoryFake();
      StoreController controller = new StoreController(categoryRepository);

      // Act
      ViewResult result = controller.Index() as ViewResult;

      // Assert
      Assert.IsNotNull(result);
      Assert.AreEqual("Index", result.ViewName);
   }
}

Veja bem: Nós já implementamos uma forma do pattern injeção de dependência (Constructor Injection). O nosso repositório não é mais instanciado dentro do Controller, mas é “injetado” através do construtor (linha 8). Daí vem a “tal” Inversion of Control, pois a responsabilidade de instanciar o repositório não é mais do Controller, mas de alguma outra classe. Em outras palavras, quem controla qual “versão” do repositório será utilizada pelo Controller não é mais o próprio Controller.

Isso funciona, mas temos alguns problemas. Imagine a situação de utilizarmos vários repositórios no nosso Controller… Teríamos que ter vários parâmetros no nosso construtor, além de termos uma dependência no mínimo “incômoda” do construtor sem parâmetros com a implementação do repositório “verdadeiro”.

O que fazer então? É aí que entram em cena os container‘s de IoC. Mas esse é exatamente o assunto principal desse post, e vai ser tratado na segunda parte, onde iremos configurar o container de IoC Ninject utilizando o NuGet usando esse mesmo exemplo.

Forte abraço.

Usando o NBuilder para criação de objetos “fake”

1 dez

Pessoal,

Recentemente descobri (não sei se vocês já conheciam) uma ferramenta bem interessante, que tem ajudado bastante na criação de stub‘s para os testes de unidade. Trata-se do NBuilder (http://nbuilder.org).

O NBuilder é um projeto open source, que permite criar objetos a partir das suas classes muito rapidamente, através de uma interface fluente e extensível. Ele instancia os objetos e atribui automaticamente valores às propriedades e campos públicos da sua classe, além de permitir que você substitua os valores das propriedades dos objetos criados usando expressões lambda.

Bom, como sempre, vamos aos exemplos práticos que sempre são mais elucidativos que a teoria. Acredito que rapidamente vocês vão entender a “mão na roda” que essa ferramenta é. Para que você possa reproduzir esses exemplos, basta fazer o download do NBuilder e referenciá-lo no seu projeto.

Tomando como exemplo esse domínio:

public class Blog : IBusinessEntity
{
   public int Id { get; set; }
   public string Name { get; set; }
   public IList Posts { get; set; }
}

public class Post : IBusinessEntity
{
   public int Id { get; set; }
   public string Title { get; set; }
   public string Text { get; set; }
   public string Author { get; set; }
}

Criei alguns testes de unidade para exemplificar a utilização do NBuilder:

[TestMethod]
public void Build_Blog()
{
	// Arrange

	// Act
	var blog = Builder<Blog>.CreateNew().Build();

	// Assert
	Assert.IsNotNull(blog);
	Assert.AreEqual(1, blog.Id);
	Assert.AreEqual("Name1", blog.Name);
}

Perceberam o que o método Builder<Blog>.CreateNew() fez? Ele instanciou um objeto do tipo Blog e preencheu as propriedades Id e Name apropriadamente, e o método Build() nos retornou o objeto. Simples demais.

Podemos também criar listas de objetos muito facilmente:

[TestMethod]
public void Build_ListOfPosts()
{
	// Arrange

	// Act
	var posts = Builder<Post>.CreateListOfSize(10).Build();

	// Assert
	Assert.AreEqual(10, posts.Count);
	Assert.AreEqual(1, posts.First().Id);
	Assert.AreEqual(10, posts.Last().Id);
	Assert.AreEqual("Title1", posts.First().Title);
	Assert.AreEqual("Title10", posts.Last().Title);
	Assert.AreEqual("Text1", posts.First().Text);
	Assert.AreEqual("Text10", posts.Last().Text);
	Assert.AreEqual("Author1", posts.First().Author);
	Assert.AreEqual("Author10", posts.Last().Author);
}

Muito legal. O método Builder<Post>.CreateListOfSize(int) instanciou 10 objetos do tipo Post, preencheu as propriedades apropriadamente e os retornou em um IList<Post>:

  • A propriedade Id (do tipo int), recebeu os valores 1, 2, …, 10;
  • A propriedade Title (do tipo string), recebeu os valores “Title1”, “Title2”, …, “Title10”;
  • A propriedade Author (do tipo string), recebeu os valores “Author1”, “Author2”, …, “Author10”.
  • Etc…

No primeiro exemplo, a propriedade Posts (que é um IList<Post>) do objeto Blog não foi preenchida. Para que essa propriedade seja preenchida, precisamos usar o método With:

[TestMethod]
public void Build_ListOfBlogsWithPosts()
{
	// Arrange
	var posts = Builder<Post>.CreateListOfSize(10).Build();

	// Act
	var blog = Builder<Blog>.CreateNew()
                       .With(b => b.Posts = posts).Build();

	// Assert
	Assert.IsNotNull(blog);
	Assert.AreEqual(10, blog.Posts.Count);
	Assert.AreEqual(1, blog.Posts.First().Id);
	Assert.AreEqual(10, blog.Posts.Last().Id);
	Assert.AreEqual("Title1", blog.Posts.First().Title);
	Assert.AreEqual("Title10", blog.Posts.Last().Title);
}

Esses são exemplos bem simples, mas nos dá uma idéia do que podemos fazer com a ferramenta. Temos vários outros métodos, que nos permite:

Bem, isso foi só uma amostra do que é possível fazer com o NBuilder, vale muito a pena dar uma olhada.

Em um próximo post vou mostrar algumas “coisas” um pouco mais complexas que já fiz com ele, além de mostrar como o tenho utilizado juntamente com o Moq (http://code.google.com/p/moq), para criação de stub‘s nos testes de unidade.

Forte abraço.