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

Published: (March 3, 2026 at 08:42 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Introdução

Os testes unitários são essenciais no desenvolvimento de software, pois garantem a qualidade e a confiabilidade do código. No caso de aplicações que utilizam o Entity Framework Core 8, testar a lógica que interage com o banco de dados pode ser desafiador. Uma solução eficiente é criar mocks do DbContext, permitindo testar a lógica de negócio sem depender de um banco de dados real.

Por que mockar o DbContext?

  • Isolamento – Permite testar a lógica de negócio separadamente, sem depender de um banco de dados real.
  • Desempenho – Reduz o tempo dos testes, eliminando operações de entrada e saída (I/O).
  • Confiabilidade – Garante que os testes sejam reproduzíveis e consistentes.

Mockar métodos assíncronos do EF Core, como ToListAsync ou FirstOrDefaultAsync, pode ser desafiador porque o EF Core utiliza IAsyncEnumerable e IAsyncQueryProvider para implementar essas operações. É necessário simular corretamente o comportamento dessas interfaces assíncronas.

Pré‑requisitos

PacoteComando
Entity Framework Core 8dotnet add package Microsoft.EntityFrameworkCore
EF Core InMemory (opcional)dotnet add package Microsoft.EntityFrameworkCore.InMemory
Moq (mocking)dotnet add package Moq
xUnit (framework de testes)dotnet add package xUnit
MockQueryable (simulação de métodos assíncronos)dotnet add package MockQueryable.Moq

Certifique‑se de que a aplicação está configurada para utilizar a versão mais recente do EF Core e que os pacotes estejam devidamente instalados.

Criando um DbSet falso com suporte a operações assíncronas

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 Produtos { get; set; } = null!;
    public AppDbContext() { }
}

Essas classes representam um cenário comum de uma aplicação CRUD, onde manipulamos objetos de domínio como Produto através de um contexto do EF Core.

Mockando o DbContext

var dadosFalsos = new List
{
    new Produto { Id = 1, Nome = "Produto A", Preco = 10.0m },
    new Produto { Id = 2, Nome = "Produto B", Preco = 20.0m }
};

var mockSet = dadosFalsos.AsQueryable().BuildMockDbSet();
mockSet.Setup(x => x.FindAsync(It.IsAny()))
       .ReturnsAsync((object[] input) =>
           dadosFalsos.FirstOrDefault(p => p.Nome == (string)input[0]));

var mockContext = new Mock();
mockContext.Setup(c => c.Produtos).Returns(mockSet.Object);

Serviço de exemplo

public class ProdutoService
{
    private readonly AppDbContext _context;

    public ProdutoService(AppDbContext context)
    {
        _context = context;
    }

    public async Task ObterProdutoPorNomeAsync(string nome)
    {
        return await _context.Produtos.FirstOrDefaultAsync(p => p.Nome == nome);
    }
}

Teste unitário do serviço

using Xunit;
using MockQueryable.Moq;
using System.Threading.Tasks;

public class ProdutoServiceTests
{
    [Fact]
    public async Task ObterProdutoPorNomeAsync_DeveRetornarProdutoCorreto()
    {
        // Arrange
        var dadosFalsos = new List
        {
            new Produto { Id = 1, Nome = "Produto A", Preco = 10.0m },
            new Produto { Id = 2, Nome = "Produto B", Preco = 20.0m }
        };

        var mockSet = dadosFalsos.AsQueryable().BuildMockDbSet();
        mockSet.Setup(x => x.FindAsync(It.IsAny()))
               .ReturnsAsync((object[] input) =>
                   dadosFalsos.FirstOrDefault(p => p.Nome == (string)input[0]));

        var mockContext = new Mock();
        mockContext.Setup(c => c.Produtos).Returns(mockSet.Object);

        var service = new ProdutoService(mockContext.Object);

        // Act
        var resultado = await service.ObterProdutoPorNomeAsync("Produto A");

        // Assert
        Assert.Equal("Produto A", resultado?.Nome);
    }
}

Conclusão

Mockar o DbContext com suporte a métodos assíncronos no Entity Framework Core 8 pode ser desafiador, mas é uma prática valiosa para criar testes rápidos e confiáveis. A configuração correta permite que você teste a lógica de negócio isoladamente, garantindo qualidade e eficiência no desenvolvimento. Ao dominar essas técnicas, é possível construir aplicações robustas, com código testável e confiável, essencial para um desenvolvimento ágil e sustentável.

0 views
Back to Blog

Related posts

Read more »