c# - 我的模拟 DbContext 使用 Moq 在单元测试中写入数据库

标签 c# entity-framework unit-testing moq

我是模拟和使用最小起订量的新手。这是我第一次尝试模拟添加功能。我有模拟设置,它适用于读取函数,但是当我尝试对添加方法进行单元测试时,它会将更改保存到数据库。

如何模拟 add 方法?

我想我必须模拟我的 UnitOfWork 类,它有 SaveChanges() 方法。我想知道如何设置模拟以拦截对 SaveChanges() 的调用而不保存到数据库。

这是我到目前为止的模拟

[SetUp]
    public void SetUp()
    {
        addCount = 0;

        IEnumerable<Platform> platformList = new List<Platform>(){
            new Platform() { Id = 1, Name = "Unknown"},
            new Platform() { Id =2, Name = "Amazon"},
            new Platform() { Id = 3, Name = "Prime Pantry"}
        };
        var platformData = platformList.AsQueryable();

        var mockPlatformSet = new Mock<DbSet<Platform>>();
        mockPlatformSet.As<IQueryable<Platform>>().Setup(m => m.Provider).Returns(platformData.Provider);
        mockPlatformSet.As<IQueryable<Platform>>().Setup(m => m.Expression).Returns(platformData.Expression);
        mockPlatformSet.As<IQueryable<Platform>>().Setup(m => m.ElementType).Returns(platformData.ElementType);
        mockPlatformSet.As<IQueryable<Platform>>().Setup(m => m.GetEnumerator()).Returns(platformData.GetEnumerator());
        mockPlatformSet.Setup(m => m.Add(It.IsAny<Platform>())).Callback(() => addCount++);

        var mockContext = new Mock<ApplicationDbContext>(){ CallBase = true };
        mockContext.Setup(m => m.Platforms).Returns(mockPlatformSet.Object);
        mockContext.Setup(m => m.Platforms.Add(It.IsAny<Platform>()));
        mockContext.Setup(m => m.Platforms.Add(It.IsAny<Platform>())).Callback(() => addCount++);


        unitOfWork = new UnitOfWork(mockContext.Object);
        platformRepo = new PlatformRepository(mockContext.Object);

        controller = new PlatformController(platformRepo, unitOfWork);
    }

添加 UnitOfWork 代码

public class UnitOfWork : IUnitOfWork 
{
    private readonly DbContext _context;
    private bool _isDisposed = false;

    public UnitOfWork(DbContext context)
    {
        _context = context;
    }

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

    protected virtual void Dispose(bool disposing)
    {
        if (!_isDisposed)
        {
            if (disposing)
            {
                _context.Dispose();
            }
        }
        _isDisposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

}

更新问题

我正在尝试对 PlatformControllerCreate 方法进行单元测试。在这个方法中,我调用存储库上的 Add 函数,然后调用 UnitOfWorkSaveChanges 函数。我想验证我的 Platform 对象是否已添加到 DbSet,但“拦截”了对 SaveChanges() 的调用,因为它不会写入数据库。

我该怎么做?

最佳答案

当我设置 CallBase我的值(value)mockContext作为IUnitOfWorkfalse ,这似乎解决了我单元测试写入数据库的问题。

这行代码: mockContext.As<IUnitOfWork>().CallBase = false;

这是我的 Setup 的代码功能

[SetUp]
    public void SetUp()
    {
        addCount = 0;

        IEnumerable<Platform> platformList = new List<Platform>(){
            new Platform() { Id = 1, Name = "Unknown"},
            new Platform() { Id =2, Name = "Amazon"},
            new Platform() { Id = 3, Name = "Prime Pantry"}
        };
        var platformData = platformList.AsQueryable();

        var mockPlatformSet = new Mock<DbSet<Platform>>();
        mockPlatformSet.As<IQueryable<Platform>>().Setup(m => m.Provider).Returns(platformData.Provider);
        mockPlatformSet.As<IQueryable<Platform>>().Setup(m => m.Expression).Returns(platformData.Expression);
        mockPlatformSet.As<IQueryable<Platform>>().Setup(m => m.ElementType).Returns(platformData.ElementType);
        mockPlatformSet.As<IQueryable<Platform>>().Setup(m => m.GetEnumerator()).Returns(platformData.GetEnumerator());
        mockPlatformSet.Setup(m => m.Add(It.IsAny<Platform>())).Callback(() => addCount++);

        var mockContext = new Mock<ApplicationDbContext>(){ CallBase = true };
        mockContext.Setup(m => m.Platforms).Returns(mockPlatformSet.Object);
        mockContext.Setup(m => m.Platforms.Add(It.IsAny<Platform>()));
        mockContext.Setup(m => m.Platforms.Add(It.IsAny<Platform>())).Callback(() => addCount++);
        mockContext.Setup(m => m.Set<Platform>()).Returns(mockPlatformSet.Object);
        mockContext.As<IUnitOfWork>().CallBase = false;

        unitOfWork = new UnitOfWork(mockContext.Object);
        platformRepo = new PlatformRepository(mockContext.Object);

        controller = new PlatformController(platformRepo, unitOfWork);
    }

关于c# - 我的模拟 DbContext 使用 Moq 在单元测试中写入数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26302058/

相关文章:

c# - 监视 Azure Blob 存储中的容器是否发生更改的最佳方法是什么?

c# - DES 加密不工作 C#

c# - 将 DataGridView 中的时间格式化为本地时区

c# - Identity.EntityFramework OnModelCreating 是如何调用的

c# - 将 GUID 转换为字符串 Entity Framework

unit-testing - Moq-ing 类或接口(interface)有什么区别?

python - 如何在 Django 中测试文件响应?

c# - 构造函数参数枚举和魔术字符串

sql - 序列不包含任何元素 - LINQ、MVC、Average

c++ - 在 Linux 上测试网络代码的最准确方法是什么?