.Net Framework, .Net Core e .Net Standard

Com o lançamento do novo Visual Studio 2017 e as novas opções da plataforma .Net disponíveis, os termos .Net Core, .Net Framework, e .Net Standard ficaram meio confusos.

Recentemente li um artigo interessante que me ajudou a entender a diferença entre esses termos e gostaria de escrever sobre o assunto.

.Net Core

O .Net Core é a novidade no mundo .Net. Sua característica mais importante é ser cross-plataform, isto é, ser suportado em diferentes plataformas. Ele suporta o desenvolvimento de software para Windows, Linux e MacOS.

O .Net Core não possui alguns dos recursos mais comuns do .Net Framework, portanto, ele dificilmente poderá ser aplicado em ambientes legados ou ambientes desenvolvidos anteriormente ao seu lançamento.

Seu uso deve ser encarado principalmente em novos desenvolvimentos.

E o .Net Standard / netstandard?

O nome .Net Standard é referente as bibliotecas do .Net. Elas garantem uma sintonia maior do .Net Core com o .Net Framework e o Mono.

.Net Standard também é o nome do build target (usado como “netstandard”) de aplicações .Net.

A Microsoft padronizou as APIs de runtime da plataforma .NET para possibilitar que um código seja compatível com diferentes runtimes.

Nem todas as classes existentes foram padronizadas para esse suporte e é aí que entra o .Net Standard para definir quais APIs funcionam entre as diversas implementações do .Net.

Um ponto importante é que o .Net Standard é suportado em diferentes níveis dependendo da versão utilizada. Se você está desenvolvendo um código para funcionar em diferentes versões do .Net, você terá que usar uma versão da biblioteca .Net Standard que seja comum nos targets desejados.

Por exemplo, o .Net Standard 1.2 suporta: .Net Framework 4.5.1, Windows e Windows Phone 8.1. Mas, se você também quiser que o código funcione no Windows 8.0, será necessário utilizar o .Net Standard 1.1 que usa o .Net Framework 4.5. Com isso, o código pode perder algumas features presentes na versão mais avançada do .Net Framework.

A documentação oficial da Microsoft possui uma tabela mostrando as versões do .Net Standard e sua correspondência com outras implementações da plataforma.

O importante disso tudo é tomar cuidado para informar o target correto do .Net Standard que será utilizado.

 

 

O princípio Tell, Don’t Ask

Este princípio da orientação a objetos diz respeito sobre um objeto dizer o que faz ao invés de perguntar.

Para entender melhor, vou dar um exemplo com duas classes.

A classe Square que representa um quadrado.

namespace TellDontAsk
{
	public class Square
	{
		public int Height { get; private set; }
		public int Width { get; private set; }

		public Square(int height, int width)
		{
			Height = height;
			Width = width;
		}
	}
}

E a classe Paint que tem a função de desenhar um quadrado.

namespace TellDontAsk
{
	public class Paint
	{
		public Paint()
		{
		}

		public Square DrawASquare(int height, int width)
		{
			var square = new Square(height, width);

			if (square.Height != square.Width)
				throw new Exception("A square needs height equals width");

			return square;
		}
	}
}

Se tentarmos desenhar um quadrado com altura diferente da largura a classe vai dar erro e informar que um quadrado precisa ter a altura igual a largura.

Mas, qual o problema dessa classe de acordo com o princípio “Tell, Don’t Ask”?

Devemos dizer ao objeto o que queremos que ela faça, e não perguntar sobre ele mesmo, fazer uma decisão, e então dizer para ele o que fazer.

Para corrigir isso, podemos encapsular esse código dentro da própria classe Square, deixando essa regra no seu devido lugar.

A classe Square vai ficar da seguinte maneira:

namespace TellDontAsk
{
	public class Square
	{
		public int Height { get; private set; }
		public int Width { get; private set; }

		public Square(int height, int width)
		{
			Height = height;
			Width = width;

			Validate();
		}

		public void Validate()
		{
			if (Height != Width)
				throw new Exception("A square needs height equals width");
		}
	}
}

Já a classe Paint vai se abstrair de tomar a decisão de se o objeto Square é válido ou não.

namespace TellDontAsk
{
	public class Paint
	{
		public Paint()
		{
		}

		public Square DrawASquare(int height, int width)
		{
			return new Square(height, width);
		}
	}
}

Não aplicar esse princípio no código pode acarretar na existência de determinadas regras em lugares incorretos.

Se esse fosse um sistema mais complexo, a alteração de uma simples regra poderia ocasionar o aparecimento de vários defeitos pelo código. Uma vez que a regra não estaria no lugar correto e seria necessário buscá-la em todo o código.

O encapsulamento no lugar correto é a solução para garantir o comportamento esperado do objeto.

O código completo do projeto está no GitHub, basta clicar aqui para vê-lo.

Se quiserem conhecer mais sobre mim, basta ir aqui no blog no menu quem sou e conferir também o meu LinkedIn.

Se ficou alguma dúvida, comenta aqui no blog que eu tento ajudar. 🙂

Compilando uma aplicação .NET Core em um runtime específico

Neste post vou explicar como fazer para o .NET Core compilar uma aplicação em um runtime específico detalhando os runtimes desejados no project.json.

Em um post anterior (Criando um projeto .NET Core usando a linha de comando e o Visual Studio Code) eu expliquei como criar uma aplicação simples. Vou usar esse mesmo projeto neste post.

Ao abrir o arquivo project.json temos a seguinte configuração:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.1"
        }
      },
      "imports": "dnxcore50"
    }
  }
}

Para uma aplicação .NET Core em um runtime específico devemos remover o atributo “type”: “platform” das dependences dentro das especificações dos frameworks, neste caso, netcoreapp1.0.

Nesse projeto só é preciso fazer isso na dependência Microsoft.NETCore.App. O atributo vai ficar como o código abaixo.

        "Microsoft.NETCore.App": {
          "version": "1.0.1"
        }

O próximo passo é adicionar o atributo runtimes ao arquivo project.json. O atributo runtimes define para quais runtimes o projeto deve ser compilado. A documentação oficial possui uma lista de runtimes disponíveis através da explicação do .NET Core Runtime IDentifier (RID).

Neste caso, vou usar o Windows 10. Para isso é preciso informar no arquivo project.json o identificador do runtime desejado como win10-x64.

Por fim, o arquivo project.json vai ficar da seguinte maneira:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "version": "1.0.1"
        }
      },
      "imports": "dnxcore50"
    }
  },
  "runtimes": {
    "win10-x64": {}
  }
}

Agora, ao usar o comando dotnet restore seguido do dotnet build a compilação gerada será especificamente para Windows 10 e estará no caminho \bin\Debug\netcoreapp1.0\win10-x64.

Quando o projeto é compilado para um runtime específico ele possibilita usar o comando dotnet publish. Ele copia o executável, as DLLs e o framework para um diretório publish dentro do diretório do runtime especificado. Neste caso, \bin\Debug\netcoreapp1.0\win10-x64\publish.

É possível notar que agora, dentro do diretório publish, temos o nosso executável e todas as DLLs necessárias, inclusive as do .NET Core, como mostra a imagem abaixo:

Captura de Tela 2016-12-07 às 22.53.36.png

Com isso feito, é possível executar a aplicação em qualquer computador com Windows 10, mesmo que ele não tenha o .NET Core instalado.

O código completo do projeto está no GitHub, basta clicar aqui para vê-lo.

Se quiserem conhecer mais sobre mim, basta ir aqui no blog no menu quem sou e conferir também o meu LinkedIn.

Se ficou alguma dúvida, comenta aqui no blog que eu tento ajudar. 🙂

 

Criando um projeto .NET Core usando a linha de comando e o Visual Studio Code

Nesse post vou explicar como criar um projeto novo com .NET Core usando apenas alguns comandos e o Visual Studio Code.

O .NET Core é uma plataforma de desenvolvimento mantida pela Microsoft e pela comunidade .NET. Ela é suportada no Windows, no macOS e no Linux.

O passo inicial é acessar o site da Microsoft e seguir o guia que ensina como instalar o .NET Core. Basta clicar aqui e seguir os passos.

Também vamos precisar usar o Visual Studio Code. Assim como o .NET Core, ele também possui versões para Windows, macOS e Linux. Basta clicar aqui e seguir com a instalação no seu sistema operacional.

Para iniciar, você deve criar uma pasta para o projeto. Neste caso, foi criada a pasta DotNetCoreConsoleSample. Você pode fazer isso manualmente ou direto pela linha de comando.

Agora, usando a linha de comando no seu sistema operacional, vá até o diretório do projeto e use o comando dotnet new. A resposta deve ser uma mensagem semelhante a essa: Created new C# project in DotNetCoreConsoleSample.

O comando dotnet new pode ser usado juntamente com a opção -t acompanhada do tipo do projeto, podendo ser um console, web, lib ou xunittest. Por exemplo, o comando dotnet new -t web, cria um projeto web. Na documentação oficial temos todas as opções disponíveis para esse comando.

O próximo passo é usar o comando dotnet restore. Esse comando chama o NuGet e restaura os pacotes que estão informados no atributo dependences dentro do arquivo project.json. Ele também cria o project.lock.json. Uma explicação bem detalhada sobre o comando pode ser encontrada aqui.

Ao abrir a pasta do projeto com o Visual Studio Code você deverá ver algo como a imagem abaixo.

dotnetnew

Ao abrir o arquivo project.json temos a seguinte configuração:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.1"
        }
      },
      "imports": "dnxcore50"
    }
  }
}

Cada um desses atributos significa uma especificação para o projeto.

  • version: é a versão do projeto. Se o projeto fosse uma lib, ele poderia representar a versão do pacote NuGet a ser gerado.
  • buildOptions: controla as especificações de compilação do projeto.
  • debugTipe: indica o tipo de arquivo .PDB (arquivo que contém as informações para o debugger funcionar corretamente) a ser gerado. É usada a opção portable para projetos .NET Core.
  • emitEntryPoint: é um boolean que informa se a compilação deve criar um executável (.exe).
  • dependences: é aqui que colocamos os pacotes a serem usados no projeto.
  • frameworks: informa o framework do projeto.

Na documentação oficial tem um artigo que explica todas as opções existentes e suportadas no project.json.

Ao abrir o arquivo Program.cs temos o código que exibe um Hello World.

using System;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

Por fim, é só usar o comando dotnet run para executar a aplicação. Esse comando chama o dotnet build e logo após já executa a aplicação.

O resultado deve ser algo como a imagem abaixo:

dotnetrun

O código completo do projeto está no GitHub, basta clicar aqui para vê-lo.

Se quiserem conhecer mais sobre mim, basta ir aqui no blog no menu quem sou e conferir também o meu LinkedIn.

Se ficou alguma dúvida, comenta aqui no blog que eu tento ajudar. 🙂

Criando uma resposta personalizada de erro no ASP .NET WEB API com IHttpActionResult

No artigo “Criando Action Results (IHttpActionResult) personalizados no ASP .NET WEB API” aqui do blog expliquei mais detalhadamente como criar uma classe de resposta personalizada. E nesse artigo vou dar uma ideia de uma classe que se encaixa melhor no uso do dia-a-dia.

Em um exemplo mais real, podemos criar uma resposta personalizada chamada ErrorResult que retorna um HTTP status code de internal server error e um objeto de exceção contendo algumas informações padrões.

 namespace LuizPauloPradoBlog.WebApi.ActionResults
{
    public class ErrorResult : IHttpActionResult
    {
        private HttpRequestMessage _request;
        private Dictionary<string, string> _customizedException;

        public ErrorResult(HttpRequestMessage request, Exception ex)
        {
            _request = request;
            _customizedException = CreateCustomizedException(ex);
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = new HttpResponseMessage()
            {
                Content = new StringContent(JsonConvert.SerializeObject(_customizedException)),
                StatusCode = HttpStatusCode.InternalServerError
            };

            return Task.FromResult(response);
        }

        private Dictionary<string, string> CreateCustomizedException(Exception ex)
        {
            var message = ex.Message;
            var innerMessage = ex.InnerException == null ? string.Empty : ex.InnerException.Message;

            var customizedException = new Dictionary<string, string>();
            customizedException.Add("Message", message);
            customizedException.Add("InnerMessage", innerMessage);

            return customizedException;
        }
    }
}

Ao chamar a resposta de ErrorResult, é passado um objeto de Exception e dentro da classe tratamos ele para somente retornar a mensagem de erro e a mensagem de erro interna. Quando o ExecuteAsync é chamado, o nosso objeto é convertido para JSON e é retornado na reposta HTTP.

Neste caso, isso é feito para não expor todo o objeto de Exception, que pode conter informações sigilosas da aplicação.

[HttpGet]
public IHttpActionResult Get(string name)
{
    try
    {
        var item = _sampleData.Single(x => x == name);
        return Ok(item);
    }
    catch (Exception ex)
    {
        return new ErrorResult(Request, ex);
    }
}

Com isso, sempre que a controller soltar uma exceção, podemos tratá-la e retornar somente as informações relevantes para o usuário.
O código completo do projeto está no GitHub, basta clicar aqui para vê-lo.
Se quiserem conhecer mais sobre mim, basta ir aqui no blog no menu quem sou e conferir também o meu LinkedIn.

Se ficou alguma dúvida, comenta aqui no blog que eu tento ajudar. 🙂

Criando Action Results (IHttpActionResult) personalizados no ASP .NET WEB API

Neste artigo vou explicar como criar um Action Result, herdado da interface IHttpActionResult , no ASP .NET WEB API.

De modo geral, a interface IHttpActionResult representa a criação de repostas HTTP na nossa controller. Ela basicamente representa uma factory de respotas HTTP usando HttpResponseMessage.

Quem quiser mais detalhes, aqui no blog tem o post para entender a diferença entre os Action Results IHttpActionResult e HttpResponseMessage que explica o assunto.

No trecho de código abaixo temos dois exemplos de tipos de respostas IHttpActionResult que geralmente são usados em métodos de controllers.

[HttpGet]
public IHttpActionResult Get()
{
    if (_sampleData == null)
        return NotFound();

    return Ok();
}

O Ok() representa uma resposta HTTP que se refere a um status code de OK. Já a resposta NotFound(), representa uma resposta  HTTP que se refere a um status code de not found.

Para criar uma resposta personalizada, precisamos criar uma classe que implemente a interface IHttpActionResult e tenha um método chamado ExecuteAsync.

namespace System.Web.Http
{
    public interface IHttpActionResult
    {
        Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken);
    }
}

O método ExecuteAsync é chamado para criar um objeto  HttpResponseMessage, que representa uma reposta HTTP dentro da nossa aplicação. Nele é possível usar todas as funções desta classe e manipular a resposta a ser criada. O retorno do método é uma Task, que quando executada, vai conter o objeto de resposta HTTP.

Para entender melhor como tudo funciona, vamos criar uma resposta de exemplo.

namespace LuizPauloPradoBlog.WebApi.ActionResults
{
    public class SampleResult : IHttpActionResult
    {
        private string _message;

        public SampleResult()
        {
            _message = "OK " + DateTime.Now.ToShortDateString();
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = new HttpResponseMessage()
            {
                Content = new StringContent(_message)
            };

            return Task.FromResult(response);
        }
    }
}

No exemplo acima foi criada uma resposta chamada SampleResponse que retorna sempre uma mensagem de OK com a data atual.

[HttpGet]
public IHttpActionResult Get()
{
    return new SampleResult();
}

Ao instanciar nosso SampleResult na controller, a classe irá internamente criar uma mensagem e executar o ExecuteAsync para criar a resposta HTTP.

O código completo do projeto está no GitHub, basta clicar aqui para vê-lo.

Se quiserem conhecer mais sobre mim, basta ir aqui no blog no menu quem sou e conferir também o meu LinkedIn.

Se ficou alguma dúvida, comenta aqui no blog que eu tento ajudar. 🙂

Entenda a diferença entre JSON e JSONB no PostgresSQL

No Postgres é possível armazenar valores contendo JSON nos tipos de dado json e jsonb. Neste artigo vou explicar um pouco sobre cada um.

A função desses tipos de dados no Postgres não é somente armazenar um valor, é armazenar a informação e efetuar uma validação no formato do dado. O próprio Postgres usa as especificações oficiais RFC 7159.

A principal diferença entre eles é que o tipo de dado jsonb consiste em armazenar a informação de maneira binária e o tipo de dado json é armazenado como texto.

O fato de ser armazenado em notação binária confere ao jsonb a vantagem de poder ser indexado,  não manter informações com espaços em branco, salvar o dado sem levar em consideração a ordem dos registros (“chave”: “valor”) e não manter chaves duplicadas.

Segundo a documentação oficial do Postgres, a vantagem do jsonb consiste no seu poder de processamento, que é mais rápido que o processamento do dado do tipo json, pois ele não precisa efetuar a conversão da informação sempre que for usá-la.

Ao executar alguma operação em um objeto do tipo json, por exemplo, o processamento pode ficar mais lento, uma vez que o Postgres efetua uma conversão interna do dado toda vez que ele é usado. Com o jsonb, isso não ocorre dessa maneira.

Se for necessário somente armazenar a informação e não fazer muitas manipulações ou operações, o tipo mais indicado é o json.

Se for necessário armazenar a informação e fazer operações nela, ou também precisar realizar alguma indexação, o tipo mais indicado é o jsonb.

A documentação do Postgres tem um tópico só sobre JSON. Vale a pena conferir para entender mais.

Testando Entity Framework com Effort

Neste artigo vou explicar como criar testes unitários para Entity Framework usando o Effort.

Effort é um framework que ajuda na criação de testes para Entity Framework. Ele é um provider ADO.NET que executa todas as operações em uma base de dados em memória e em tempo de execução. Diferentemente do provider padrão do Entity Framework, ele não usa base de dados tradicional.

Como base vamos criar algumas classes modelo usando o Entity Framework. No artigo anterior que ensina a testar Entity Framework com Moq eu crio essas classes de exemplo. As mesmas também serão utilizadas aqui.

Para inciar temos que alterar o nosso Context do Entity Framework e adicionar um novo construtor.

namespace LuizPauloPradoBlog.Repository.Context
{
    public class CarShoppingContext : DbContext
    {
        public CarShoppingContext() { }
        public CarShoppingContext(DbConnection connection) : base(connection, true) { }

        public virtual DbSet<Car> Cars { get; set; }
    }
}

Esse novo construtor serve para que seja possível criar uma nova conexão (objeto DbConnection) com o Effort e usá-la na nossa classe. O segundo valor corresponde ao parâmetro contextOwnsConnection. Sua definição, na documentação da Microsoft, consiste em não efetuar um dispose na conexão quando for efetuado um dispose no Context também (the connection will not be disposed when the context is disposed if contextOwnsConnection is false). Por isso, usaremos o seu valor como true, pois queremos que o Context efetue dispose na conexão e evite que muito lixo fique em memória por conta dos testes unitários.

Feito isso, vamos adicionar um projeto de unit test na nossa Solution no Visual Studio. Nesse projeto devemos instalar o pacote Effort através do nuget (Install-Package Effort).

Para começar, vamos adicionar o método Initialize() na nossa classe de testes. Nele vamos criar uma nova conexão usando o Effort.

namespace LuizPauloPradoBlog.Tests
{
    [TestClass]
    public class CarShoppingContextTestWithEffort
    {
        private CarShoppingContext _context;
        private ICarRepository _repository;

        [TestInitialize]
        public void Initialize()
        {
            var connection = Effort.DbConnectionFactory.CreateTransient();

            _context = new CarShoppingContext(connection);
            _repository = new CarRepository(_context);
        }
    }
}

A documentação do Effort explica que o código Effort.DbConnectionFactory.CreateTransient() cria um objeto do tipo DbConnection que faz a conexão com a nossa base de dados em memória.

Usaremos essa conexão para instanciar a nossa classe de Context e consequentemente usaremos a mesma para instanciar o nosso repositório. Esses objetos serão usados durante a construção dos nossos métodos de teste.

O primeiro método será o ShouldCreateNewCar(), que testa criação de um registro novo. Usaremos o Assert.IsTrue para confirmar que nosso objeto foi adicionado.

[TestMethod]
public void ShouldCreateNewCar()
{
    var car = new Car() { Name = "Fiesta", Model = "Fiesta SE", YearOfManufacture = 2015 };
    _repository.Add(car);

    Assert.IsTrue(car.Id != 0);
}

O segundo método será o ShouldGetCarById(), que testa a criação de um registro e em seguida já efetua a sua busca, usando o seu Id, no nosso repositório. O Assert.IsNotNull verifica se o objeto foi encontrado e o Assert.IsTrue faz as comparações necessárias para confirmar que o objeto é o mesmo que foi adicionado.

[TestMethod]
public void ShouldGetCarById()
{
    var sampleCar = new Car() { Name = "Fiesta", Model = "Fiesta SE", YearOfManufacture = 2015 };
    _repository.Add(sampleCar);

    var car = _repository.Get(sampleCar.Id);

    Assert.IsNotNull(car);
    Assert.IsTrue(car.Id != 0);
    Assert.IsTrue(car.Name == sampleCar.Name);
    Assert.IsTrue(car.Model == sampleCar.Model);
    Assert.IsTrue(car.YearOfManufacture == sampleCar.YearOfManufacture);
}

O terceiro método será o ShouldGetAllCars(), que testa a criação de alguns registros de exemplo e em seguida faz uma listagem deles através do repositório. O Assert.IsNotNull verifica se a listagem foi efetuada e o Assert.IsTrue valida se os mesmos registros foram retornados.

[TestMethod]
public void ShouldGetAllCars()
{
    var sampleCarFiesta = new Car() { Name = "Fiesta", Model = "Fiesta SE", YearOfManufacture = 2015 };
    var sampleCarGolf = new Car() { Name = "Golf", Model = "Golf Sport", YearOfManufacture = 2015 };
    _repository.Add(sampleCarFiesta);
    _repository.Add(sampleCarGolf);

    var cars = _repository.GetAll();

    Assert.IsNotNull(cars);
    Assert.IsTrue(cars.Any());
    Assert.IsTrue(cars[0].Id == sampleCarFiesta.Id);
    Assert.IsTrue(cars[1].Id == sampleCarGolf.Id);
}

Captura de Tela 2016-07-13 às 23.31.44

O projeto de exemplo completo pode ser encontrado no meu GitHub.

Se quiserem conhecer mais sobre mim, basta ir aqui no blog no menu quem sou e conferir também o meu LinkedIn.

Se ficou alguma dúvida, comenta aqui no blog que eu tento ajudar. 🙂

Testando Entity Framework com Moq

Neste artigo vou explicar como fazer teste unitário para Entity Framework utilizando o pacote Moq do C#. Com ele podemos simular comportamentos específicos em nossas classes e configurar cenários de testes.

Antes de começar, vamos criar uma estrutura simples de objeto, entidade e respositório com Entity Framework.

namespace LuizPauloPradoBlog.Repository.Model
{
    public class Car
    {
        public int Id { get; set; }
        public string Model { get; set; }
        public string Name { get; set; }
        public int YearOfManufacture { get; set; }
    }
}
namespace LuizPauloPradoBlog.Repository.Context
{
    public class CarShoppingContext : DbContext
    {
        public CarShoppingContext() { }

        public virtual DbSet<Car> Cars { get; set; }
    }
}
namespace LuizPauloPradoBlog.Repository
{
    public class CarRepository : ICarRepository
    {
        private readonly CarShoppingContext _context;

        public CarRepository(CarShoppingContext context)
        {
            _context = context;
        }

        public IList<Car> GetAll()
        {
            return _context.Cars.ToList();
        }

        public Car Get(int id)
        {
            return _context.Cars.FirstOrDefault(x => x.Id == id);
        }

        public void Add(Car car)
        {
            _context.Cars.Add(car);
            _context.SaveChanges();
        }
    }
}

Com essa estrutura básica criada, basta adicionar um novo projeto do tipo Unit Test no Visual Studio clicando em Solution > Add > New Project > Test > Unit Test Project.

Um ponto importante antes de começar a escrever os testes é lembrar-se de instalar o pacote Moq.

Install-Package Moq -Version 4.5.10

Screenshot_1

Moq (ou Mock) é um framework para realizar e configurar simulações em métodos e classes. A configuração de um objeto usando Moq é bem conveniente para se criar testes unitários e simular comportamentos que validem o funcionamento em determinados cenários.

Para inciar, vamos fazer um teste que chama o repositório e realiza a inclusão de um novo registro. Nesse exemplo vamos fazer o teste criando o método ShouldCreateNewCar(). Para isso, é preciso fazer um mock do DbSet do objeto, um mock do Context do Entity Framework e um mock da classe de repositório.

A notação consiste em instanciar um objeto Mock informando o tipo de objeto que deverá ser simulado. A linha de código fica da seguinte maneira: new Mock.

Logo abaixo temos um mock do nosso objeto DbSet.

var _dbSet = new Mock<DbSet<Car>>();

O próximo passo é fazer o mesmo com o Context do Entity Framework. Aqui entra o conceito de efetuar uma configuração (usando o método Setup) do nosso objeto mock para especificar um comportamento do mesmo. Neste caso, devemos configurá-lo para retornar um DbSet especifico ao chamar a nossa entidade de exemplo.

var _dbSet = new Mock<DbSet<Car>>();

var _context = new Mock<CarShoppingContext>();
_context.Setup(x => x.Cars).Returns(_dbSet.Object);

Com isso feito, usaremos os objetos mock como parâmetro na classe de repositório. Ela será instanciada no teste e receberá os objetos que criamos. Isso irá permitir testar a classe usando objetos de simulação que possuem o comportamento que configuramos anteriormente.

namespace LuizPauloPradoBlog.WebApi.Tests
{
    [TestClass]
    public class CarShoppingContextTestWithMock
    {
        [TestMethod]
        public void ShouldCreateNewCar()
        {
            var _dbSet = new Mock<DbSet<Car>>();

            var _context = new Mock<CarShoppingContext>();
            _context.Setup(x => x.Cars).Returns(_dbSet.Object);

            var _repository = new CarRepository(_context.Object);

            var sampleCar = new Car() { Id = 3, Name = "Civic", Model = "Honda Civic SE", YearOfManufacture = 2016 };

            _repository.Add(sampleCar);

            _dbSet.Verify(m => m.Add(It.IsAny<Car>()), Times.Once());
            _context.Verify(m => m.SaveChanges(), Times.Once());
        }
    }
}

Após isso, para validar o comportamento do que foi executado, usaremos o método Verify para confirmar que um objeto foi adicionado ao DbSet e também confirmar que o método de SaveChanges do Context foi devidamente acionado.

No segundo teste vamos chamar o repositório e realizar a listagem de alguns registros. Nesse exemplo vamos criar o método ShouldGetAllCars().

A preparação dos objetos mock seguem a mesma lógica do teste anterior. A diferença fica por conta de incluir registros de teste no DbSet e efetuar as configurações de um IQueryable que represente o nosso DbSet.

namespace LuizPauloPradoBlog.WebApi.Tests
{
    [TestClass]
    public class CarShoppingContextTestWithMock
    {
        [TestMethod]
        public void ShouldGetAllCars()
        {
            var sampleData = new List<Car>()
            {
                new Car() { Id = 1, Name = "Fiesta", Model = "Fiesta SE", YearOfManufacture = 2015 },
                new Car() { Id = 2, Name = "Golf", Model = "Golf Sport", YearOfManufacture = 2015 }
            }.AsQueryable();

            var _dbSet = new Mock<DbSet<Car>>();
            _dbSet.As<IQueryable<Car>>().Setup(x => x.Provider).Returns(sampleData.Provider);
            _dbSet.As<IQueryable<Car>>().Setup(x => x.Expression).Returns(sampleData.Expression);
            _dbSet.As<IQueryable<Car>>().Setup(x => x.ElementType).Returns(sampleData.ElementType);
            _dbSet.As<IQueryable<Car>>().Setup(x => x.GetEnumerator()).Returns(sampleData.GetEnumerator());

            var _context = new Mock<CarShoppingContext>();
            _context.Setup(x => x.Cars).Returns(_dbSet.Object);

            var _repository = new CarRepository(_context.Object);

            var cars = _repository.GetAll();

            Assert.IsNotNull(cars);
            Assert.IsTrue(cars.Any());
        }
    }
}

Neste caso, efetuamos a criação de uma lista de registros de exemplo como IQueryable e configuramos o mock do DbSet para utilizá-la. Ao chamar o método de GetAll() no repositório, o mesmo deve retornar exatamente os dados de exemplo que configuramos.

Por fim, podemos organizar melhor a configuração dos objetos de mock no método Initialize da classe de testes. O resultado ficou assim:

namespace LuizPauloPradoBlog.WebApi.Tests
{
    [TestClass]
    public class CarShoppingContextTestWithMock
    {
        private Mock<DbSet<Car>> _dbSet;
        private Mock<CarShoppingContext> _context;
        private ICarRepository _repository;

        [TestInitialize]
        public void Initialize()
        {
            var sampleData = new List<Car>()
            {
                new Car() { Id = 1, Name = "Fiesta", Model = "Fiesta SE", YearOfManufacture = 2015 },
                new Car() { Id = 2, Name = "Golf", Model = "Golf Sport", YearOfManufacture = 2015 }
            }.AsQueryable();

            _dbSet = new Mock<DbSet<Car>>();
            _dbSet.As<IQueryable<Car>>().Setup(x => x.Provider).Returns(sampleData.Provider);
            _dbSet.As<IQueryable<Car>>().Setup(x => x.Expression).Returns(sampleData.Expression);
            _dbSet.As<IQueryable<Car>>().Setup(x => x.ElementType).Returns(sampleData.ElementType);
            _dbSet.As<IQueryable<Car>>().Setup(x => x.GetEnumerator()).Returns(sampleData.GetEnumerator());

            _context = new Mock<CarShoppingContext>();
            _context.Setup(x => x.Cars).Returns(_dbSet.Object);

            _repository = new CarRepository(_context.Object);
        }

        [TestMethod]
        public void ShouldCreateNewCar()
        {
            var sampleCar = new Car() { Id = 3, Name = "Civic", Model = "Honda Civic SE", YearOfManufacture = 2016 };
            _repository.Add(sampleCar);

            _dbSet.Verify(m => m.Add(It.IsAny<Car>()), Times.Once());
            _context.Verify(m => m.SaveChanges(), Times.Once());
        }

        [TestMethod]
        public void ShouldGetAllCars()
        {
            var cars = _repository.GetAll();

            Assert.IsNotNull(cars);
            Assert.IsTrue(cars.Any());
        }
    }
}

O projeto de exemplo pode ser encontrado no meu GitHub.

Pra quem quer pesquisar mais, o framework Moq possui muitas outras opções de métodos disponíveis, vale a pena conferir a documentação dele.

Se ficou alguma dúvida, comenta aqui no blog que eu tento ajudar. 🙂

Entenda a diferença entre os Action Results IHttpActionResult e HttpResponseMessage

Aqui no blog tem dois posts sobre teste unitário para controllers no ASP.NET Web API 2, um que explica como fazer usando o HttpResponseMessage e outro que explica usando o IHttpActionResult.

Nesse post vou explicar a diferença entre ambos para que seja possível entender melhor quando usar cada uma deles.

No ASP .NET Web API 2 temos dois tipos de action results que correspondem a uma resposta HTTP da controller: HttpResponseMessage e IHttpActionResult.

Dependendo de qual for escolhido, a controller usa maneiras diferentes de criar a resposta HTTP.

No HttpResponseMessage a controller retorna diretamente uma resposta HTTP. Isto é feito através da criação de um objeto resposta do HttpResponseMessage que possui suas propriedades preenchidas semelhante a uma resposta HTTP convencional.  É possível configurar o conteúdo da resposta, o tipo do dado retornado, ou até mesmo configurar os cabeçalhos dela.

HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);
response.Content = new StringContent("Blog", Encoding.UTF8);
response.Headers.Location = new Uri("https://luizpauloprado.com.br");
response.Headers.Date = new DateTimeOffset(DateTime.UtcNow);
response.Headers.CacheControl = new CacheControlHeaderValue() { MaxAge = TimeSpan.FromMinutes(30) };

return response;

Em resumo, pode-se dizer que o HttpResponseMessage possibilita um controle bem maior sobre a criação de um resposta HTTP na controller.

Já no IHttpActionResult temos o mesmo conceito de resposta HTTP, só que de maneira mais simplificada e encapsulada. Ele basicamente representa uma factory de HttpResponseMessage.

public IHttpActionResult Get(int id)
{
    var sampleObject = _repository.Get(id);

    if (sampleObject == null)
        return NotFound();

    return Ok(sampleObject);
}

Na documentação oficial do ASP .NET Web API 2 tem uma explicação mais detalhada sobre tudo isso. Vale a pena conferir.