gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 20:09:24 30 4
gpt4 key购买 nike

我是 Moq 的新手,想将其用作数据的后备存储 - 但不接触实时数据库。

我的设置如下:

  • 一个 UnitOfWork 包含所有存储库,并用于整个应用程序的数据访问。
  • Repository 代表 DbContext 提供的 DbSet 的直接 Hook 。
  • DbContext 包含所有 DbSet。

到目前为止,这是我的测试:

        // ARRANGE
var user = new User()
{
FirstName = "Some",
LastName = "Guy",
EmailAddress = "some.guy@mockymoqmoq.com",
};

var mockSet = new MockDbSet<User>();
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());

我的测试似乎是成功的,因为它可以验证用户是否已添加到模拟 DbSet - 但我需要做的实际上是取回该数据并对其执行进一步的断言(这只是一个临时的测试)。

请指教,测试框架正在努力。此外,如果它们更易于使用,我可以选择迁移到其他测试框架。

谢谢。

更新:这是我的工作代码。

单元测试

        // ARRANGE
var user = new User()
{
FirstName = "Some",
LastName = "Guy",
EmailAddress = "some.guy@mockymoqmoq.com",
};

var mockSet = new MockDbSet<User>();
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());

// TODO: Further assertations can now take place by accessing mockSet.BackingStore.
}

模拟数据库

class MockDbSet<TEntity> : Mock<DbSet<TEntity>> where TEntity : class
{
public ICollection<TEntity> BackingStore { get; set; }

public MockDbSet()
{
var queryable = (this.BackingStore ?? (this.BackingStore = new List<TEntity>())).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());

// Mock the insertion of entities
this.Setup(e => e.Add(It.IsAny<TEntity>())).Returns((TEntity entity) =>
{
this.BackingStore.Add(entity);

return entity;
});

// TODO: Other DbSet members can be mocked, such as Remove().
}
}

最佳答案

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

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
}
}

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

// 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
}

关于c# - 如何使用 Entity Framework 和 Moq 进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45558470/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com