You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

对注入DbContext参数的控制器进行单元测试报错如何解决?

问题根源

你遇到的报错和真实数据库连接没有关系,是Mock配置不完整导致的,具体原因如下:

  • 直接MockToDoContext时,没有为TodoItem属性(即DbSet<TodoItem>类型)设置Mock返回值,执行到_context.TodoItem.FindAsync()逻辑时会先抛出空引用异常
  • FindAsync是DbSet<T>的方法,你原本的写法直接在DbContext层面设置FindAsync的Mock规则,根本不会生效

解决方案

提供两种可直接运行的实现方案:

方案1:使用EF Core内存数据库(推荐)

这是微软官方推荐的EF Core业务逻辑单元测试方案,不需要复杂Mock配置,更贴近真实运行场景,首先需要在测试项目安装Nuget包Microsoft.EntityFrameworkCore.InMemory,测试代码如下:

[Fact]
public async Task GetTodoItem_WithUnexistingItem_ReturnsNotFound()
{
    // Arrange 为每个测试用例生成独立的内存数据库,避免数据互相干扰
    var options = new DbContextOptionsBuilder<ToDoContext>()
        .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
        .Options;

    using var context = new ToDoContext(options);
    var controller = new TodoItemsController(context);

    // Act
    var result = await controller.GetTodoItem(long.MinValue);

    // Assert
    Assert.IsType<NotFoundResult>(result.Result);
}

方案2:使用Moq完整Mock依赖

如果要坚持用纯Mock的方式实现,需要先MockDbSet<TodoItem>再绑定到Mock的DbContext上,测试代码如下:

[Fact]
public async Task GetTodoItem_WithUnexistingItem_ReturnsNotFound()
{
    // Arrange 先Mock DbSet<TodoItem>,配置FindAsync的返回规则
    var mockDbSet = new Mock<DbSet<TodoItem>>();
    mockDbSet.Setup(ds => ds.FindAsync(It.IsAny<long>()))
        .ReturnsAsync((TodoItem)null);

    // 再Mock ToDoContext,绑定上面生成的Mock DbSet
    var dbContextStub = new Mock<ToDoContext>(new DbContextOptions<ToDoContext>());
    dbContextStub.Setup(context => context.TodoItem)
        .Returns(mockDbSet.Object);

    var controller = new TodoItemsController(dbContextStub.Object);

    // Act
    var result = await controller.GetTodoItem(long.MinValue);

    // Assert
    Assert.IsType<NotFoundResult>(result.Result);
}

如果后续需要测试查询存在数据的场景,纯Mock方案还需要额外配置DbSet的IQueryable相关实现,内存数据库方案不需要额外修改,会更省心。


内容的提问来源于stack exchange,提问作者MrEmper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 13:24:04