使用Moq进行单元测试 - 值不能为空
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Moq进行单元测试 - 值不能为空相关的知识,希望对你有一定的参考价值。
我正在使用EF6。生成的代码类似于:
public partial class MyDataContext : DbContext
{
public MyDataContext() : base("name=mydata")
{
}
public virtual DbSet<Book> Books { get; set; }
}
然后我有一个通用的存储库,如:
public class GenericRepository<TObject> where TObject : class
{
protected readonly MyDataContext Context;
protected GenericRepository(MyDataContext context)
{
Context = context;
}
public virtual DbSet<TObject> GetAll()
{
return Context.Set<TObject>();
}
}
然后我有一个使用GenericRepository返回数据的服务:
public class MyDataService<TObject> where TObject : class
{
private readonly MyDataContext context;
public MyDataService(MyDataContext ct)
{
context = ct;
}
public ICollection<TObject> GetAll()
{
var r = new GenericRepository<TObject>(context);
return r.GetAll().ToList();
}
}
所以我可以用这样的东西得到所有的书:
var ds = new MyDataService<Book>(new MyDataContext());
var data = ds.GetAll();
这工作正常。接下来我尝试使用Moq对以上代码进行单元测试:
var books = new List<Book>
{
new Book {Id = 1, Name = "BBB"},
new Book {Id = 2, Name = "ZZZ"},
new Book {Id = 3, Name = "AAA"},
}.AsQueryable();
var mockSet = new Mock<DbSet<Book>>();
mockSet.As<IQueryable<Book>>().Setup(m => m.Provider).Returns(books.Provider);
mockSet.As<IQueryable<Book>>().Setup(m => m.Expression).Returns(books.Expression);
mockSet.As<IQueryable<Book>>().Setup(m => m.ElementType).Returns(books.ElementType);
mockSet.As<IQueryable<Book>>().Setup(m => GetEnumerator()).Returns(books.GetEnumerator());
var mockContext = new Mock<MyDataContext>();
mockContext.Setup(c => c.Books).Returns(mockSet.Object);
var service = new MyDataService<Book>(mockContext.Object);
var data = service.GetAll();
但是,我在最后一行得到"Value cannot be null.
Parameter name: source"
错误。当我进入代码时,我看到上下文对象中的Books集合为空。
我究竟做错了什么?
答案
这是因为测试在数据上下文中设置.Setup(c => c.Books)
,但在实际代码中访问Context.Set<TObject>()
方法中的GetAll()
,因此对于测试,它最终将成为null
。
尝试改为
mockContext.Setup(c => c.Set<Book>()).Returns(mockSet.Object);
以上是关于使用Moq进行单元测试 - 值不能为空的主要内容,如果未能解决你的问题,请参考以下文章