C# 模拟实体DbContext插入
我正在使用Xunit和Moq。我希望能够模拟表中的插入。这样,记录实际上不会填充表,但单元测试可以验证插入是否成功。使用真实的DbContext,单元测试适用于下面的方法Add_works()。当我尝试模拟时,在Add\u WantToWork()中,我得到错误,“对象引用未设置为对象的实例”。失败发生在Context.set().Add(entity)中的ARepository类中,如下所示。它由uw.Table1.Add(_Table1)调用C# 模拟实体DbContext插入,c#,unit-testing,entity-framework-6,moq,xunit,C#,Unit Testing,Entity Framework 6,Moq,Xunit,我正在使用Xunit和Moq。我希望能够模拟表中的插入。这样,记录实际上不会填充表,但单元测试可以验证插入是否成功。使用真实的DbContext,单元测试适用于下面的方法Add_works()。当我尝试模拟时,在Add\u WantToWork()中,我得到错误,“对象引用未设置为对象的实例”。失败发生在Context.set().Add(entity)中的ARepository类中,如下所示。它由uw.Table1.Add(_Table1)调用 public class UnitTestCla
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);
}
}
公共类UnitTestClass
{
私有只读表1_Table1=新表1()
{
TypeId=4,
Name=“测试自动化”,
Description=“测试自动化”,
CreatedDate=DateTime.Now
};
[事实]
公共空间添加工程()
{
int rowsAffected=0;
使用(var uw=new UnitOfWork(new PortalDbContext()))
{
uw.表1.添加(_.表1);
rowsAffected=uw.Commit();
}
Assert.Equal(1,行受影响);
}
[事实]
公共无效添加\ u WantToWork()
{
int rowsAffected=0;
var mockContext=new Mock();
使用(var uw=newunitofwork(mockContext.Object))
{
uw.表1.添加(_.表1);
rowsAffected=uw.Commit();
}
Assert.Equal(1,行受影响);
}
}
公共抽象类ARepository:IRepository
其中tenty:类,tenty
{
受保护的只读DbContext上下文;
受保护的存储库(DbContext上下文)
{
上下文=上下文;
}
公共无效添加(TEntity实体)
{
Context.Set().Add(实体);
}
}
问题在于,您模拟的是对象,而不是对象的方法。
应该是这样的:
mockContext.Setup(p => p.Set<Table1>().Add(It.IsAny<Table1>())).Returns(_table1);
mockContext.Setup(p=>p.Set().Add(It.IsAny()).Returns(_table1);
通过这种方式,mock将创建dbSet的一个实例,并将返回您想要的任何内容。过去,我只经历过模拟它的发生,而不是数据库获取了记录。这属于集成测试领域,这是我所不擅长的。我过去用它来完成一个模拟
[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());
}
[TestMethod]
public void CreateBlog通过上下文()保存日志
{
var mockSet=new Mock();
var mockContext=new Mock();
Setup(m=>m.Blogs).Returns(mockSet.Object);
var service=newblogservice(mockContext.Object);
AddBlog(“ADO.NET博客”http://blogs.msdn.com/adonet");
验证(m=>m.Add(It.IsAny()),Times.Once());
验证(m=>m.SaveChanges(),Times.Once());
}
注意下面几行。这些只是验证是否调用了add方法和save changes。这是否足以解决您的挑战
mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());
mockContext.Verify(m => m.SaveChanges(), Times.Once());
mockSet.Verify(m=>m.Add(It.IsAny()),Times.Once());
验证(m=>m.SaveChanges(),Times.Once());
如果您使用的是EntityFramework,您应该能够找到一些库,这些库允许您模拟DBContext。我可以模拟DBContext。我的问题是当我尝试向模拟的DbContext添加对象时。我是EntityFrameworkMock库的维护者,该库在和上可用。它基于最小起订量,因此您可以使用已知的设置和验证方法。这很有效。谢谢<代码>mockContext.Setup(p=>p.Set().Add(It.IsAny())).Returns(_table1)代码>System.NotSupportedException未由用户代码处理。Message=非虚拟(在VB中可重写)成员上的设置无效:m=>m.Table1s。我在mockContext.Setup(m=>m.Table1s.Returns(mockSet.Object)