且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用 Entity Framework 和 Moq 进行单元测试?

更新时间:2023-11-17 08:14:58

您只需要创建一个集合作为后备存储,并使用后备集合模拟枚举数据库集

You just need to create a collection to act as the backing store and mock the enumeration db set with the backing collection

public class MockDbSet<TEntity> : Mock<DbSet<TEntity>> where TEntity : class {
    public MockDbSet(List<TEntity> dataSource = null) {
        var data = (dataSource ?? new List<TEntity>());
        var queryable = data.AsQueryable();

        this.As<IQueryable<TEntity>>().Setup(e => e.Provider).Returns(queryable.Provider);
        this.As<IQueryable<TEntity>>().Setup(e => e.Expression).Returns(queryable.Expression);
        this.As<IQueryable<TEntity>>().Setup(e => e.ElementType).Returns(queryable.ElementType);
        this.As<IQueryable<TEntity>>().Setup(e => e.GetEnumerator()).Returns(() => queryable.GetEnumerator());
        //Mocking the insertion of entities
        this.Setup(_ => _.Add(It.IsAny<TEntity>())).Returns((TEntity arg) => {
            data.Add(arg);
            return arg;
        });

        //...the same can be done for other members like Remove
    }
}

所以现在您可以使用列表来保存数据

So now you can use a list to hold the data

// ARRANGE
var dataSource = new List<User>(); //<-- this will hold data
var user = new User()
{
    FirstName = "Some",
    LastName = "Guy",
    EmailAddress = "some.guy@mockymoqmoq.com",
};

var mockSet = new MockDbSet<User>(dataSource);
var mockContext = new Mock<WebAPIDbContext>();

mockContext.Setup(c => c.Set<User>()).Returns(mockSet.Object);

// ACT
using (var uow = UnitOfWork.Create(mockContext.Object))
{
    uow.UserRepository.Add(user);
    uow.SaveChanges();


    // ASSERT
    mockSet.Verify(u => u.Add(It.IsAny<User>()), Times.Once());
    Assert.IsTrue(dataSource.Contains(user)); //<-- shows mock actually added item
    Assert.IsTrue(uow.UserRepository.Any(u => u == user)); //<-- show you can actually query mock DbSet
}