.NET Core下NUnit与Entity Framework集成测试依赖注入问题
嘿,这个问题我之前帮同事解决过,刚好能给你捋清楚怎么弄!
首先,咱们得明白:.NET Core的内置DI不会自动在测试项目里初始化,不像ASP.NET Core项目那样有现成的容器。所以咱们得在TestBase里手动搭建DI容器,这样才能在[OneTimeSetUp]和[OneTimeTearDown]里拿到需要的服务(比如你的EF Core DbContext)。
下面是具体的实现步骤和代码示例:
1. 在TestBase中构建DI容器
咱们要在[OneTimeSetUp]方法里初始化服务集合,注册所有需要的服务(包括DbContext和业务服务),然后构建ServiceProvider。
2. 借助Scope获取Scoped服务
EF Core的DbContext默认是Scoped生命周期的,所以不能直接从ServiceProvider获取,得创建一个服务范围(Scope)来获取,避免生命周期管理问题。
完整的TestBase示例代码
using Microsoft.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore; using NUnit.Framework; public class TestBase { protected IServiceProvider ServiceProvider { get; private set; } [OneTimeSetUp] public void GlobalTestSetup() { // 1. 初始化服务集合 var services = new ServiceCollection(); // 2. 注册EF Core DbContext(这里用SQL Server举例,也可以换成内存数据库) services.AddDbContext<YourTestDbContext>(options => options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=YourTestDb;Trusted_Connection=True;")); // 3. 注册其他你需要的服务(比如业务逻辑服务) services.AddScoped<IYourBusinessService, YourBusinessService>(); // 4. 构建服务提供器 ServiceProvider = services.BuildServiceProvider(); // 5. 创建测试数据库并初始化 using var scope = ServiceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService<YourTestDbContext>(); dbContext.Database.EnsureCreated(); // 自动创建数据库和表 } [OneTimeTearDown] public void GlobalTestTeardown() { // 1. 删除测试数据库 using var scope = ServiceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService<YourTestDbContext>(); dbContext.Database.EnsureDeleted(); // 彻底删除数据库 // 2. 释放服务提供器资源 if (ServiceProvider is IDisposable disposableProvider) { disposableProvider.Dispose(); } } }
几个关键注意点:
- 内存数据库选项:如果不想用真实的SQL Server,也可以换成内存数据库,只需要把
UseSqlServer换成UseInMemoryDatabase("YourTestDb"),但要注意内存数据库在不同Scope里的隔离性,根据你的测试需求调整。 - 服务生命周期:对于Scoped和Transient服务,一定要通过
CreateScope()获取,用完后Scope会自动释放资源;Singleton服务可以直接从ServiceProvider获取。 - 测试类继承:你的测试类只需要继承这个
TestBase,就能自动执行数据库的创建和清理,而且在测试方法里也可以通过ServiceProvider.CreateScope()获取需要的服务。
这样就能解决你在[OneTimeSetUp]和[OneTimeTearDown]里无法访问DI服务的问题啦!
内容的提问来源于stack exchange,提问作者Andy Furniss
相关产品推荐
相关产品推荐

