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. 🙂