模拟实体 DbContext 插入
Mock an Entity DbContext Insert
我正在使用 Xunit & Moq。我希望能够模拟插入 table。这样,记录实际上不会填充 table,但单元测试可以验证插入是否成功。使用真实的 DbContext,单元测试适用于下面的方法 Add_Works()。当我尝试使用 Mock 时,在 Add_WantToWork() 中,我得到错误,"Object reference not set to an instance of an object." 失败发生在 Context.Set().Add(entity) 在 ARepository class 中,也如下所示。它由 uw.Table1.Add(_table1).
调用
public class UnitTestClass
{
private readonly Table1 _table1 = new Table1()
{
TypeId = 4,
Name = "TestAutomation",
Description = "Test Automation",
CreatedDate = DateTime.Now
};
[Fact]
public void Add_Works()
{
int rowsAffected = 0;
using (var uw = new UnitOfWork(new PortalDbContext()))
{
uw.Table1.Add(_table1);
rowsAffected = uw.Commit();
}
Assert.Equal(1, rowsAffected);
}
[Fact]
public void Add_WantToWork()
{
int rowsAffected = 0;
var mockContext = new Mock<TestDbContext>();
using (var uw = new UnitOfWork(mockContext.Object))
{
uw.Table1.Add(_table1);
rowsAffected = uw.Commit();
}
Assert.Equal(1, rowsAffected);
}
}
public abstract class ARepository<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{
protected readonly DbContext Context;
protected ARepository(DbContext context)
{
Context = context;
}
public void Add(TEntity entity)
{
Context.Set<TEntity>().Add(entity);
}
}
问题是您在模拟对象,但没有模拟对象的方法。
它会是这样的:
mockContext.Setup(p => p.Set<Table1>().Add(It.IsAny<Table1>())).Returns(_table1);
这样 mock 将创建一个 dbSet 的实例,并且return你想要的任何东西
过去,我的经验只是嘲笑它发生了,而不是数据库记录了记录。这属于集成测试领域,这超出了我的专业知识。我过去曾使用 this method 来完成模拟。
[TestMethod]
public void CreateBlog_saves_a_blog_via_context()
{
var mockSet = new Mock<DbSet<Blog>>();
var mockContext = new Mock<BloggingContext>();
mockContext.Setup(m => m.Blogs).Returns(mockSet.Object);
var service = new BlogService(mockContext.Object);
service.AddBlog("ADO.NET Blog", "http://blogs.msdn.com/adonet");
mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());
mockContext.Verify(m => m.SaveChanges(), Times.Once());
}
注意以下几行。这些只是验证调用了添加方法并调用了保存更改。这足以解决您的挑战吗?
mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());
mockContext.Verify(m => m.SaveChanges(), Times.Once());
我正在使用 Xunit & Moq。我希望能够模拟插入 table。这样,记录实际上不会填充 table,但单元测试可以验证插入是否成功。使用真实的 DbContext,单元测试适用于下面的方法 Add_Works()。当我尝试使用 Mock 时,在 Add_WantToWork() 中,我得到错误,"Object reference not set to an instance of an object." 失败发生在 Context.Set().Add(entity) 在 ARepository class 中,也如下所示。它由 uw.Table1.Add(_table1).
调用public class UnitTestClass
{
private readonly Table1 _table1 = new Table1()
{
TypeId = 4,
Name = "TestAutomation",
Description = "Test Automation",
CreatedDate = DateTime.Now
};
[Fact]
public void Add_Works()
{
int rowsAffected = 0;
using (var uw = new UnitOfWork(new PortalDbContext()))
{
uw.Table1.Add(_table1);
rowsAffected = uw.Commit();
}
Assert.Equal(1, rowsAffected);
}
[Fact]
public void Add_WantToWork()
{
int rowsAffected = 0;
var mockContext = new Mock<TestDbContext>();
using (var uw = new UnitOfWork(mockContext.Object))
{
uw.Table1.Add(_table1);
rowsAffected = uw.Commit();
}
Assert.Equal(1, rowsAffected);
}
}
public abstract class ARepository<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{
protected readonly DbContext Context;
protected ARepository(DbContext context)
{
Context = context;
}
public void Add(TEntity entity)
{
Context.Set<TEntity>().Add(entity);
}
}
问题是您在模拟对象,但没有模拟对象的方法。 它会是这样的:
mockContext.Setup(p => p.Set<Table1>().Add(It.IsAny<Table1>())).Returns(_table1);
这样 mock 将创建一个 dbSet 的实例,并且return你想要的任何东西
过去,我的经验只是嘲笑它发生了,而不是数据库记录了记录。这属于集成测试领域,这超出了我的专业知识。我过去曾使用 this method 来完成模拟。
[TestMethod]
public void CreateBlog_saves_a_blog_via_context()
{
var mockSet = new Mock<DbSet<Blog>>();
var mockContext = new Mock<BloggingContext>();
mockContext.Setup(m => m.Blogs).Returns(mockSet.Object);
var service = new BlogService(mockContext.Object);
service.AddBlog("ADO.NET Blog", "http://blogs.msdn.com/adonet");
mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());
mockContext.Verify(m => m.SaveChanges(), Times.Once());
}
注意以下几行。这些只是验证调用了添加方法并调用了保存更改。这足以解决您的挑战吗?
mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());
mockContext.Verify(m => m.SaveChanges(), Times.Once());