繁体   English   中英

如何使用 Moq 对我的 EF 存储库方法进行单元测试?

[英]How to unit test my EF repository method using Moq?

我正在尝试为其使用 DbContext 和 Add 方法的 Create 方法为我的存储库类编写一个单元测试。

我的想法是计算现有记录的数量。 调用创建方法。 获取新的记录计数并检查它是否增加了 1。

但是,在运行单元测试时,调用 Add 方法时出错,并出现以下错误:

{"Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.\r\nObject name: 'DbContext'."}

我试图理解为什么会这样以及如何克服这个问题?

public class MyDatabaseContext : DbContext
{
    public MyDatabaseContext(DbContextOptions<MyDatabaseContext> options) : base(options)
    {
    }

    public DbSet<Record> Records { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Record>();
    }
}

public class Repository : IRepository
{
    private readonly MyDatabaseContext _dbContext;

    public Repository(MyDatabaseContext dbContext)
    {
        _dbContext = dbContext;
    }

    public Record Create(Record record)
    {
        try
        {
            using (_dbContext)
            {
                var response = _dbContext.Records.Add(record); //erroring line
                _dbContext.SaveChanges();
                return response.Entity;
            }
        }
        catch (Exception ex)
        {
            return null;
        }
    }
    
    public IEnumerable<Record> GetAll()
    {
        try
        {
            using (_dbContext)
            {
                return _dbContext.Records.ToList();
            }
        }
        catch (Exception ex)
        {
            return null;
        }
    }
}

public interface IRepository
{
    Record Create(Record record);
    IEnumerable<Record> GetAll();
}

启动.cs:

services.AddDbContext<MyDatabaseContext>(opt => opt.UseInMemoryDatabase("memoryDb"));
services.AddScoped<IRepository, Repository>();

单元测试:

[TestMethod]
public async Task Create_Successfully()
{
    var repository = new Repository(await GetDbContext());
    var existingRecords = repository.GetAll();

    repository.Create(new Record());
    var newRecords = repository.GetAll();

    Assert.AreEqual(3, existingRecords.Count());
    Assert.AreEqual(4, newRecords.Count());
}

private async Task<DbContext> GetDbContext()
{
    var options = new DbContextOptionsBuilder<DbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;

    var context = new DbContext(options);
    context.Database.EnsureCreated();

    if (await context.Records.CountAsync() <= 0)
    {
        for (int i = 1; i <= 3; i++)
        {
            context.Records.Add(new Records());
            await context.SaveChangesAsync();
        }
    }

    return context;
}

您需要删除GetAllCreate方法中的 using 语句:

public Record Create(Record record)
{
    try
    {
        using (_dbContext)
        {
            var response = _dbContext.Records.Add(record); //erroring line
            _dbContext.SaveChanges();
            return response.Entity;
        }
    }
    catch (Exception ex)
    {
        return null;
    }
}

至:

public Record Create(Record record)
{
    try
    {
        var response = _dbContext.Records.Add(record); //erroring line
        _dbContext.SaveChanges();
        return response.Entity;
    }
    catch (Exception ex)
    {
        return null;
    }
}

您无需担心处置服务,因为容器会在生产环境中为您执行此操作。 在你的测试中,如果你想清理东西,你可以这样做:

[TestMethod]
public async Task Create_Successfully()
{
    using (var context = await GetDbContext())
    {
        var repository = new Repository(context);
        var existingRecords = repository.GetAll();

        repository.Create(new Record());
        var newRecords = repository.GetAll();

        Assert.AreEqual(3, existingRecords.Count());
        Assert.AreEqual(4, newRecords.Count());
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM