Testando mensagens em Exceptions com MSTest

18 ago

Pessoal,

De volta ao blog, finalmente.

Todos devem saber que nos testes de unidade, quando queremos verificar se uma determinada exceção foi disparada no método que está sendo testado, se estivermos utilizando o MSTest (ferramenta de testes nativa do Visual Studio) utilizamos o atributo [ExpectedException]. Mais ou menos assim (não reparem no teste, trata-se de um exemplo):

[TestMethod]
[ExpectedException(typeof(MyBusinessException))]
public void Salvar_ComEmailDuplicado_LevantaExcecao()
{
   // Arrange
   var umaClasseDeNegocio = new ClasseDeNegocio();
   var umaEntidade = new UmaEntidade
   {
      Nome = "Nome válido",
      Email = "email@existente.com",
      Endereco = "Endereco com tamanho valido",
      Quantidade = 5
   };

   // Act
   umaClasseDeNegocio.Salvar(umaEntidade);
}

Porém, várias pessoas perguntam como fazer para, além de verificar se a exceção foi disparada, testar também a mensagem da exceção. Normalmente antes de responder, pergunto: Tem certeza que precisa testar isso?

Pergunto isso porque ficar testando pela mensagem da exceção normalmente me parece um code smell, pois em boa parte dos casos isso pode significar que poderíamos estar fazendo um tratamento de exceção mais específico, ao invés de ficar levantando exceções “genéricas” com mensagens diferentes. Mas, isso é um outro assunto – Vamos admitir que nesse caso o tratamento de exceções esteja adequado.

Infelizmente o MSTest não nos disponibiliza um atributo que permita verificar a mensagem da exceção (O NUnit disponibiliza). Assim, uma forma de fazer essa verificação é dessa forma (mais uma vez, trata-se de um exemplo):

[TestMethod]
public void Salvar_ComEmailDuplicado_LevantaExcecao()
{
   // Arrange
   var umaClasseDeNegocio = new ClasseDeNegocio();
   var umaEntidade = new UmaEntidade
   {
      Nome = "Nome válido",
      Email = "email@existente.com",
      Endereco = "Endereco com tamanho valido",
      Quantidade = 5
   };

   // Act
   try
   {
      umaClasseDeNegocio.Salvar(umaEntidade);

      // Assert
      Assert.Fail("Nenhuma exceção lançada");
   }
   catch (MyBusinessException ex)
   {
      // Assert
      Assert.AreEqual("Este e-mail já está cadastrado", ex.Message);
   }
}

Horrível. Uma outra forma de fazer, e é o que eu faço, é criar um atributo herdando da classe ExpectedExceptionBaseAttribute (o atributo [ExpectedException] também herda dela) e verificar o tipo da exceção e da mensagem. Assim:

public class ExpectedExceptionMessageAttribute
                                         : ExpectedExceptionBaseAttribute
{
   protected Type ExceptionType { get; set; }
   protected string ExceptionMessage { get; set; }

   public ExpectedExceptionMessageAttribute(Type exceptionType,
                                            string exceptionMessage)
   {
      this.ExceptionType = exceptionType;
      this.ExceptionMessage = exceptionMessage;
   }

   public ExpectedExceptionMessageAttribute(Type exceptionType, 
                                            string exceptionMessage,
                                            string noExceptionMessage)
   : base(noExceptionMessage)
   {
      this.ExceptionType = exceptionType;
      this.ExceptionMessage = exceptionMessage;
   }

   protected override void Verify(Exception exception)
   {
      if (exception.GetType() != this.ExceptionType)
      {
         var errorMessage
                 = string.Format("Test method {0} did not throw expected
                                  exception {1}.",
                                  this.TestContext.TestName,
                                  this.ExceptionType.FullName);
         throw new AssertFailedException(errorMessage);
      }

      if (exception.Message != this.ExceptionMessage)
      {
         var errorMessage
                 = string.Format("Test method {0} did not throw expected
                                  exception with message '{1}'.
                                  The message was '{2}'.", 
                                  this.TestContext.TestName,
                                  this.ExceptionMessage,
                                  exception.Message);
         throw new AssertFailedException(errorMessage);
      }
   }
}

Assim, aquele teste que verifica a mensagem ficaria assim:

[TestMethod]
[ExpectedExceptionMessage(typeof(MyBusinessException), "Este e-mail já está cadastrado")]
public void Salvar_ComEmailDuplicado_LevantaExcecao()
{
   // Arrange
   var umaClasseDeNegocio = new ClasseDeNegocio();
   var umaEntidade = new UmaEntidade
   {
      Nome = "Nome válido",
      Email = "email@existente.com",
      Endereco = "Endereco com tamanho valido",
      Quantidade = 5
   };

   // Act
   umaClasseDeNegocio.Salvar(umaEntidade);
}

Bem melhor, IMHO.

Forte abraço.

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.

Nova turma do treinamento de ASP.NET MVC no Rio de Janeiro

1 fev

Pessoal,

Muitas pessoas estão perguntando quando será a próxima turma do treinamento de ASP.NET MVC.

A última foi muito legal, a turma era boa e o feedback foi muito bom:

Porém, vou fazer a atualização do treinamento para o ASP.NET MVC 3, além de fazer alguns ajustes no treinamento em si… Porém estou em um treinamento de Windows Workflow Foundation 4 a semana toda (com o Waldemir Cambiucci, muito legal… Pretendo postar algumas coisas a respeito em breve…) e só poderei começar essas atualizações/ajustes na próxima semana.

Assim que a turma for aberta, vou divulgar por aqui e pelo twitter. Estou imaginando que a turma deva ocorrer em fevereiro ainda, mas depende principalmente da disponibilidade do laboratório em que ministramos o treinamento.

Faça o seu cadastro na lista de espera para a próxima turma clicando aqui.

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.

O que há de novo no ASP.NET MVC 3 RC 2

10 dez

Pessoal,

Foi lançado hoje o ASP.NET MVC 3 Release Candidate 2. \o/

Acabei de instalar, mas olhando as Release Notes, dá pra perceber que o que temos são alguns refactorings, alguns bug fixes e algumas pequenas melhorias. Veja a lista de ajustes, obtidas das Release Notes:

  • O template de projeto foi alterado para incluir o jQuery 1.4.4, jQuery Validation 1.7 e o jQuery UI 1.8.6;
  • Foi incluída a classe “AdditionalMetadataAttribute”, que poderá ser usado para preencher o dictionary “ModelMetadata.AdditionalValues” para uma propriedade do seu Model;
  • Os templates T4 usados para gerar as scaffolding views agora geram chamadas para os template helper’s. Por exemplo, ao invés de gerar as scaffolding views com TextBoxFor, é usado o template helper EditorFor;
  • Adicionado o método “Html.Raw”: Utilizado para exibir textos sem encoding, uma vez que por padrão o Razor faz o encode automaticamente dos valores exibidos;
  • As propriedades “Controller.ViewModel” e “View” foram renomeadas para “ViewBag”. Essas duas propriedades “apontam” para o mesmo dicionário “ViewDataDictionary”, mas tinham nomes diferentes. Foram renomeadas apenas para evitar confusão;
  • A classe “ControllerSessionStateAttribute” foi renomeada para “SessionStateAttribute”. Somente por simplicidade;
  • A propriedade “Fields” da classe “RemoteAttribute” foi renomeada para “AdditionalFields”. Somente para melhorar o entendimento da sua função;
  • A classe “SkipRequestValidationAttribute” foi renomeada para “AllowHtmlAttribute”. Somente para melhorar o entendimento da sua função;
  • Bug fix: O método “Html.ValidationMessage” agora exibe a primeira mensagem de erro “importante”, ignorando as mensagens de erro provenientes, por exemplo, de exceções ocorridas durante o model binding, que na maioria das vezes não são relevantes para o usuário da aplicação;
  • Bug fix: A declaração @model do Razor foi corrigida para não adicionar uma linha em branco no HTML gerado;
  • Breaking change: A propriedade “FileExtensions” foi adicionada às View Engines para que as View Engines possam especificar extensões de arquivo são suportadas. Assim, a View Engine Web Forms nunca irá tentar renderizar uma View cuja extensão seja “.cshtml”;
  • Bug Fix: O helper “LabelFor” foi alterado de modo a renderizar o valor correto para o atributo “For”. Anteriormente estava sendo usado o atributo “name” do input, mas de acordo com o W3C, deve ser usado o atributo “id” do input;
  • Bug Fix: O método “RenderAction” foi corrigido para que durante o model binding, o valores informados explicitamente no método “RenderAction” tenham precedência sobre os valores passados por post.

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.

Treinamento de ASP.NET MVC no Rio de Janeiro

18 nov

UPDATE 2:
Em breve abriremos uma nova turma

UPDATE 1:
A próxima turma do treinamento será realizada no seguinte período:
Dias 11, 13, 18, 19, 25, 27 de janeiro de 2011, das 18:00 às 22:00 hs.
Local: Av. Presidente Vargas, 463, 4º andar – Centro – Rio de Janeiro

Pessoal,

Preparei um treinamento de ASP.NET MVC para uma empresa de Minas Gerais, e resolvi começar a aplicá-lo aqui no Rio de Janeiro, e posteriormente em outras localidades. O treinamento ficou bem bacana, o feedback tem sido muito bom.

Quem me conhece sabe que sou um fã entusiasmado do ASP.NET MVC, e já trabalhei em dois projetos com a tecnologia, um deles com duração de 1 ano (maio/2009 a maio/2010), feito com ASP.NET MVC 1 e outro de maio/2010 até o presente momento, já utilizando o ASP.NET MVC 2. Além de participar ativamente, sempre que possível, do Fórum ASP.NET MVC do MSDN.

Além do ASP.NET MVC em si, abordaremos várias outras coisas: jQuery, testes de unidade (onde falaremos sobre mock’s, stub’s, DI, etc…), View Models, entre outros. E sempre procurando alinhar com melhores práticas de desenvolvimento (DRY, SOLID, etc…) .

Falaremos também sobre o ASP.NET MVC 3, abordando principalmente a View Engine Razor, além de apresentar (e utilizar muito!) o gerenciador de pacotes NuGet, que é incrível!

O treinamento será dado no centro do Rio de Janeiro e seu início dependerá do fechamento da turma (no mínimo 20 e no máximo 30 alunos), é em formato de workshop, é hands-on, com várias demonstrações e exercícios, ambiente de desenvolvimento virtualizado (Visual Studio 2010 / SQL Server 2008) e um aluno por máquina. Ainda por cima com um coffee break caprichado e brindes da Microsoft… Ninguém é de ferro…

Ficou interessado? Veja o prospecto do curso, com descrição, ementa, um breve currículo do instrutor (esse que vos fala), valores e formas de pagamento: Desenvolvendo Aplicações Web com ASP.NET MVC 2

Para se inscrever, clique aqui.

Para se inscrever, clique aqui.
Em breve abriremos uma nova turma

Caso queira maiores informações, você pode me contactar aqui pelo blog, por email ou pelo twitter: @andborges.

Ah, não se esqueça de divulgar! Esse treinamento poderá ser realizado em outras localidades aos sábados e poderá ser feito in-company também.

Forte abraço.

Voltando, parte 2

22 mar
Pessoal,

Mais uma vez fiquei super enrolado nesse final de fevereiro / março, mil coisas pra fazer: Visitas em casa, emprego novo, monografia, aulas, palestras, etc…
Por isso mais uma vez fiquei um tempo sem postar, mas agora estou de volta e com vários assuntos na fila.
No trabalho estou trabalhando na implantação do VSTS 2010, que estamos usando em um projeto piloto, junto a uma equipe de consultores da Microsoft.
Como é uma tecnologia novinha em folha, acho que vou conseguir fazer uns posts bem legais sobre o assunto…
Além disso, ASP.NET MVC 2, jQuery, Active Record + NHibernate, .NET 4, etc, etc, etc… Bastante assunto…
Forte abraço.