XUnit 测试 DbContext 没有处理

XUnit Test DbContext did not dispose

我正在为 DbContext 实施 XUnit 测试,DbContext 似乎没有正确处理。当我调试第一个测试时,它有效,但在第二个测试中,抛出一个错误 listAds 已经添加。

添加手表后,在第二次测试中,_context 为空,但在调用 _context.Advertisements.AddRange(listAds); 之前它具有 Advertisements 的值。

public class AdsServiceTest: IDisposable
{
    private readonly DbContextOptions<SensingSiteDbContext> _options;
    private readonly SensingSiteDbContext _context;
    private readonly AdsService _AdsService;

    public AdsServiceTest()
    {
        //initialize db options
        _options = new DbContextOptionsBuilder<SensingSiteDbContext>()
            .UseInMemoryDatabase()
            .Options;

        //get service
        _context = new SensingSiteDbContext(_options);

        //initialize dbcontext
        List<Ads> listAds = new List<Ads>() {
            new Ads(){  Id=1,AdsName="Ads1", Deleted=false},
            new Ads(){  Id=2,AdsName="Ads2", Deleted=false},
            new Ads(){  Id=3,AdsName="Ads3", Deleted=false}
        };

        //In the second test method, it throw errors, listAds already exist in 
        _context.Advertisements.AddRange(listAds);
        _context.SaveChanges();
        BaseLib.SSDbContext<Ads, AdsService> ssDbContent = new BaseLib.SSDbContext<Ads, AdsService>(_context);
        _AdsService = ssDbContent.GetService((x, y) => new AdsService(x, y));

    }

    public void Dispose()
    {
        _context.Dispose();            
    }

    [Theory]
    [InlineData(1)]
    public void FindById(int id)
    {
        Ads adsResult = _AdsService.FindById(id);
        Ads adsTarget = _context.Advertisements.Find(id);
        Assert.Equal(adsResult.AdsName, adsTarget.AdsName);
        //Assert.True(adsTarget.Equals(adsResult));
    }

    [Fact]
    public void GetAll()
    {
        var adsResult = _AdsService.GetAll();
        var adsTarget = _context.Advertisements.ToList();
        Assert.Equal(adsResult.Count(),adsTarget.Count());
        //Did not work all the time
        //Assert.True(adsTarget.Equals(adsResult));
    }
}

上下文已处理,但 "in-memory database" 本身未处理。

这 "by design" 允许您测试场景,其中 class 您测试的是创建它自己的 DBContext 实例 - 否则您无法为它们准备数据。

你有两种可能:

  1. 使用 databaseName 为每个测试创建 "different databases",代码如 .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())

  2. 在创建后(或在 Dispose 中)用 context.Database.EnsureDeleted() 强制数据库 destroy/recreate。

为了你的测试class方法2看起来更合适,但这取决于你。

文档:https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/in-memory