使用Moq进行单元测试 - 值不能为空

5

我正在使用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();

然而,我在最后一行代码中遇到了"值不能为 null。\r\n参数名: source"的错误。当我步入代码时,我发现上下文对象中的Books集合为空。
我做错了什么?

你真的需要 moq DbSet 吗(我认为不需要),你可以依赖 EF,而不是测试它。 - Lei Yang
1个回答

6

这是因为测试中设置了.Setup(c => c.Books)在数据上下文中,但实际代码中在GetAll()方法中访问Context.Set<TObject>(),所以对于测试来说,它最终将变成null

尝试更改为

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

是的,我在发布问题后意识到了这一点。谢谢! - notlkk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接