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

ASP.NET Core 1.0:如何在xUnit测试项目中注入DbContext?

问题:ASP.NET Core 1.0测试项目中如何注入ApplicationDbContext到仓储类?

我为ASP.NET Core 1.0应用创建了测试项目,其中仓储类的构造函数依赖ApplicationDbContext,现在想知道怎么在测试项目里获取并正确注入这个DbContext,完成单元测试。

我的ApplicationDbContext类代码如下:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { 
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } 
    protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); } 
    public DbSet<Category> Categories { get; set; } 
    public DbSet<Product> Products { get; set; } 
    public DbSet<ShoppingCartItem> ShoppingCartItems { get; set; } 
    public DbSet<Order> Orders { get; set; } 
    public DbSet<OrderDetail> OrderDetails { get; set; } 
}

初始的单元测试方法代码:

[Fact]
public void ProductsGetAll() { 
    //此处需要获取dbContext并注入
    ProductRepository productRepository = new ProductRepository(dbContext); 
    CategoryRepository categoryRepository = new CategoryRepository(dbContext); 
    ProductController productController = new ProductController(productRepository, categoryRepository); 
}

我已经在测试类构造函数里添加上下文实例了:

ApplicationDbContext dbContext; 
public UnitTest1() { 
    var options = new DbContextOptionsBuilder<ApplicationDbContext>() 
        .UseInMemoryDatabase(databaseName: "FakeDatabase") 
        .Options; 
    dbContext = new ApplicationDbContext(options); 
}

不过测试方法还没完成,想知道接下来该怎么处理?


解决方案

你已经选对了核心方向——用内存数据库做单元测试,既不会污染真实数据库,又能快速模拟数据交互。接下来可以按以下步骤完善测试逻辑:

1. 初始化测试数据

在测试类构造函数或者单独的初始化方法里,给内存数据库填充测试用的Product和Category数据,这样测试时才有数据可以验证:

ApplicationDbContext dbContext; 
public UnitTest1() { 
    var options = new DbContextOptionsBuilder<ApplicationDbContext>() 
        .UseInMemoryDatabase(databaseName: "FakeDatabase") 
        .Options; 
    dbContext = new ApplicationDbContext(options); 

    // 清空原有数据避免多测试干扰,再添加测试数据
    dbContext.Products.RemoveRange(dbContext.Products);
    dbContext.Categories.RemoveRange(dbContext.Categories);
    
    dbContext.Categories.AddRange(
        new Category { Id = 1, Name = "电子产品" },
        new Category { Id = 2, Name = "家居用品" }
    );
    dbContext.Products.AddRange(
        new Product { Id = 1, Name = "手机", CategoryId = 1, Price = 3999 },
        new Product { Id = 2, Name = "台灯", CategoryId = 2, Price = 99 }
    );
    dbContext.SaveChanges();
}

2. 完善测试方法的验证逻辑

现在可以实例化仓储和控制器,调用目标测试方法(比如GetAll),然后验证返回结果是否符合预期:

[Fact]
public void ProductsGetAll_ShouldReturnAllProducts() { 
    // 实例化依赖的仓储与控制器
    var productRepository = new ProductRepository(dbContext); 
    var categoryRepository = new CategoryRepository(dbContext); 
    var productController = new ProductController(productRepository, categoryRepository); 

    // 调用控制器的GetAll方法(假设你的控制器有这个方法)
    var result = productController.GetAll();

    // 验证返回结果的正确性
    var okResult = Assert.IsType<OkObjectResult>(result);
    var returnedProducts = Assert.IsType<List<Product>>(okResult.Value);
    // 验证返回的产品数量和我们初始化的一致
    Assert.Equal(2, returnedProducts.Count);
    // 可以进一步验证具体产品的属性
    Assert.Equal("手机", returnedProducts.First(p => p.Id == 1).Name);
}

3. 进阶:用DI容器模拟真实注入(可选)

如果你的项目本身依赖ASP.NET Core的DI容器,测试时也可以模拟这套逻辑,避免手动实例化所有依赖:

[Fact]
public void ProductsGetAll_WithDI_ShouldReturnAllProducts() { 
    // 构建测试用的服务容器
    var services = new ServiceCollection();
    services.AddDbContext<ApplicationDbContext>(options => 
        options.UseInMemoryDatabase("FakeDatabase_DI"));
    services.AddScoped<IProductRepository, ProductRepository>();
    services.AddScoped<ICategoryRepository, CategoryRepository>();

    var serviceProvider = services.BuildServiceProvider();
    
    // 从容器中获取仓储实例
    using var scope = serviceProvider.CreateScope();
    var productRepository = scope.ServiceProvider.GetRequiredService<IProductRepository>();
    var categoryRepository = scope.ServiceProvider.GetRequiredService<ICategoryRepository>();
    
    // 后续测试逻辑和之前一致
    var productController = new ProductController(productRepository, categoryRepository);
    var result = productController.GetAll();
    
    // 验证结果...
}

这种方式更贴近真实项目的依赖注入模式,尤其当依赖关系复杂时,能减少手动实例化的工作量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:52:09