Dispose()可成功删除DB文件,为何DisposeAsync()执行失败?
问题描述
我希望每个集成测试都创建唯一的数据库文件名,并在测试结束时将其删除。
应用代码
using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); var constr = $"DataSource={Guid.NewGuid()}.db"; builder.Services.AddDbContext<AppDbContext>(o => o.UseSqlite(constr)); var app = builder.Build(); app.Run(); public record Person(int Id); public class AppDbContext(DbContextOptions<AppDbContext> o) : DbContext(o) { public DbSet<Person> People { get; set; } } public interface IWebApiMarker;
为便于在Dispose()和DisposeAsync()间切换,我创建了编译变量SYNC,仅用于诊断,不用于生产环境。
测试代码
#define SYNC using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.DependencyInjection; namespace WebApi.Test; public class Test_1 : BaseTest { [Fact] public async Task Test() => await Task.Delay(2000); } #if SYNC public abstract class BaseTest : IDisposable #else public abstract class BaseTest : IAsyncDisposable #endif { private readonly WebApplicationFactory<IWebApiMarker> _factory; protected BaseTest() { _factory = new WebApplicationFactory<IWebApiMarker>(); using var scope = _factory.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService<AppDbContext>(); db.Database.EnsureCreated(); } #if SYNC public void Dispose() { using var scope = _factory.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService<AppDbContext>(); db.Database.EnsureDeleted(); _factory.Dispose(); } #else public async ValueTask DisposeAsync() { using var scope = _factory.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService<AppDbContext>(); db.Database.EnsureDeleted(); await _factory.DisposeAsync(); } #endif }
我无法理解为何DisposeAsync()无法在每个测试结束时删除数据库文件。
已尝试的无效方案
- 将
BaseTest()中解析的db缓存为private readonly AppDbContext db并在DisposeAsync()中复用(确保为同一对象),无效果。 - 将
db.Database.EnsureDeleted()替换为await db.Database.EnsureDeletedAsync(),无效果。 - 在测试方法中调用
DisposeAsync(),即[Fact] public async Task Test() => await DisposeAsync();,无效果且抛出异常:
System.ObjectDisposedException : 无法访问已释放的上下文实例。此错误的常见原因是释放了从依赖注入解析的上下文实例,之后又尝试在应用程序其他地方使用同一实例。这可能是因为您调用了上下文实例的“Dispose”方法,或将其包装在using语句中。若使用依赖注入,应让容器负责上下文实例的释放。
内容的提问来源于stack exchange,提问作者D G
相关产品推荐
相关产品推荐

