DEV Community

Emerson Delatorre for Fazedor de Codigo

Posted on • Originally published at fazedordecodigo.com on

Como Criar Mocks do DbContext no Entity Framework Core 8 para Testes Unitários

Os testes unitrios so essenciais no desenvolvimento de software, pois garantem a qualidade e a confiabilidade do cdigo. No caso de aplicaes que utilizam o Entity Framework Core 8, testar a lgica que interage com o banco de dados pode ser desafiador. Uma soluo eficiente criar mocks do DbContext, permitindo testar a lgica de negcio sem depender de um banco de dados real. Este artigo explica como fazer isso, abordando mtodos assncronos e os desafios relacionados.


Por que Mockar o DbContext?

Mockar o DbContext uma prtica valiosa porque:

  1. Isolamento : Permite testar a lgica de negcio separadamente, sem depender de um banco de dados real.
  2. Desempenho : Reduz o tempo dos testes, eliminando operaes de entrada e sada (I/O).
  3. Confiabilidade : Garante que os testes sejam reproduzveis e consistentes.

No entanto, mockar mtodos assncronos do Entity Framework, como ToListAsync ou FirstOrDefaultAsync, pode ser desafiador. Isso ocorre porque o EF Core utiliza IAsyncEnumerable e IAsyncQueryProvider para implementar essas operaes. Mockar esses mtodos exige simular corretamente o comportamento das interfaces assncronas, o que essencial para garantir que os testes reflitam o comportamento real da aplicao.


Configurando o Ambiente

Antes de comear, configure o ambiente com os seguintes pacotes:

  • Entity Framework Core 8
  • Moq (para criar os mocks)
  • xUnit (ou outro framework de testes unitrios)
  • MockQueryable (para simular mtodos assncronos)

Adicione os pacotes ao projeto:

# Pacote do EF Core para InMemory (opcional)dotnet add package Microsoft.EntityFrameworkCore.InMemory# Biblioteca de Mockingdotnet add package Moq# Framework de Testesdotnet add package xUnit# Biblioteca de simulao asyncdotnet add package MockQueryable.moq
Enter fullscreen mode Exit fullscreen mode

Certifique-se de que sua aplicao est configurada para utilizar a verso mais recente do EF Core e que os pacotes esto devidamente instalados.


Criando o Mock do DbContext com Mtodos Assncronos

Vamos criar um DbSet falso com suporte a operaes assncronas. Suponha que temos as seguintes classes no projeto:

public class Produto{ public int Id { get; set; } public string Nome { get; set; } = string.Empty; public decimal Preco { get; set; }}public class AppDbContext : DbContext{ public DbSet<Produto> Produtos { get; set; } = null!; public AppDbContext() { }}
Enter fullscreen mode Exit fullscreen mode

Essas classes representam um cenrio comum de uma aplicao CRUD, onde manipulamos objetos de domnio como Produto atravs de um contexto do EF Core.

Mockando o DbContext

Com o DbSet configurado, podemos mockar o DbContext para utiliz-lo nos testes:

var dadosFalsos = new List<Produto>{ new Produto { Id = 1, Nome = "Produto A", Preco = 10.0m }, new Produto { Id = 2, Nome = "Produto B", Preco = 20.0m }};var mock = dadosFalsos.AsQueryable().BuildMockDbSet();mock.Setup(x => x.FindAsync(It.IsAny<object[]>())) .ReturnsAsync((object[] input) => dadosFalsos.FirstOrDefault(x => x.Nome == (string)input[0]));var mockContext = new Mock<AppDbContext>();mockContext.Setup(c => c.Produtos).Returns(mock.Object);
Enter fullscreen mode Exit fullscreen mode

Escrevendo Testes Unitrios com Mtodos Assncronos

Agora que temos o DbContext mockado, podemos testar a lgica de negcio. Considere o seguinte servio:

public class ProdutoService{ private readonly AppDbContext _context; public ProdutoService(AppDbContext context) { _context = context; } public async Task<Produto?> ObterProdutoPorNomeAsync(string nome) { return await _context.Produtos.FirstOrDefaultAsync(x => x.Nome == nome); }}
Enter fullscreen mode Exit fullscreen mode

Para testar o mtodo ObterProdutoPorNomeAsync:

using Xunit;using MockQueryable.Moq;using System.Threading.Tasks;public class ProdutoServiceTests{ [Fact] public async Task ObterProdutoPorNomeAsync_DeveRetornarProdutoCorreto() { // Arrange var dadosFalsos = new List<Produto> { new Produto { Id = 1, Nome = "Produto A", Preco = 10.0m }, new Produto { Id = 2, Nome = "Produto B", Preco = 20.0m } }; var mock = dadosFalsos.AsQueryable().BuildMockDbSet(); mock.Setup(x => x.FindAsync(It.IsAny<object[]>())) .ReturnsAsync((object[] input) => dadosFalsos.FirstOrDefault(x => x.Nome == (string)input[0])); var mockContext = new Mock<AppDbContext>(); mockContext.Setup(c => c.Produtos).Returns(mock.Object); var service = new ProdutoService(mockContext.Object); // Act var resultado = await service.ObterProdutoPorNomeAsync("Produto A"); // Assert Assert.Equal("Produto A", resultado.Nome); }}
Enter fullscreen mode Exit fullscreen mode

Essa abordagem garante que o comportamento dos mtodos assncronos seja testado de forma eficaz, reproduzindo cenrios reais sem a necessidade de um banco de dados fsico.


Concluso

Mockar o DbContext com suporte a mtodos assncronos no Entity Framework Core 8 pode ser desafiador, mas uma prtica valiosa para criar testes rpidos e confiveis. A configurao correta permite que voc teste a lgica de negcio isoladamente, garantindo qualidade e eficincia no desenvolvimento. Ao dominar essas tcnicas, voc pode construir aplicaes robustas, com cdigo testvel e confivel, essencial para um desenvolvimento gil e sustentvel.

]]>

Top comments (0)