具有上下文的模拟通用存储库

时间:2016-03-28 16:11:42

标签: c# entity-framework unit-testing

我有几个上下文的通用存储库。我可以扩展它并将它用于服务而没有问题。但是,当我嘲笑它时,构造函数中的this.Entities总是null

GenericDataRepsository

public class GenericDataRepository<T, C> : IGenericDataRepository<T, C> where T : class where C : DbContext, new() {

    protected C context;
    protected IDbSet<T> Entities;

    public GenericDataRepository() {
        this.context = new C();
        this.Entities = context.Set<T>();
    }

    public GenericDataRepository(C context) {
        this.context = context;
        this.Entities = context.Set<T>();  // Problem is here. Entities didn't get set when mocking
    }

    public virtual IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate) {
        return Entities.Where(predicate).ToList();
    }

    // omitted Add, Update, Delte
}

单元测试

 [Test]
    public void GetBIlloTo() {
        var data = new List<BillTo> {
            new BillTo { CONTACTID = 12, COUNTRY = "USA" }
        }.AsQueryable();

        var mockSet = Substitute.For<DbSet<BillTo>, IQueryable<BillTo>>();

        ((IQueryable<BillTo>)mockSet).Provider.Returns(data.Provider);
        ((IQueryable<BillTo>)mockSet).Expression.Returns(data.Expression);
        ((IQueryable<BillTo>)mockSet).ElementType.Returns(data.ElementType);
((IQueryable<BillTo>)mockSet).GetEnumerator().Returns(data.GetEnumerator());

        var mockContext = Substitute.For<MyEntities>();
        mockContext.BillToes.Returns(mockSet);
        var repo = new GenericDataRepository<BillTo, MyEntities>(mockContext);

        //// Act
        var actual = repo.FindBy(r => r.CONTACTID == 12);

        //// Assert
        Assert.AreEqual(actual.Count(), 1);
    }

MyEntities - 由EF生成,我没有改变它。

 public partial class MyEntities : DbContext
{
    public MyEntities()
        : base("name=MyEntities")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<BillTo> BillToes { get; set; }
}

我首先使用EF数据库,NUnit和Nsu​​bstitute。也试过Moq,同样的问题。那么,为什么没有设定Entities

2 个答案:

答案 0 :(得分:3)

您没有使用方法set<T>将模拟对象设置为返回任何值。

在初始化测试类之前,只需添加以下调用:

mockContext.Set<BillTo>().Returns(mockSet);

答案 1 :(得分:1)

为什么要使用FindBy方法?为什么不使用FindAll()返回this.Entities = context.Set()之类的内容

public IQueryable<T> FindAll()
{
    return _context.Set<T>());
}

然后,存储库的用户可以使用他们想要的任何linq谓词 并且您可以模拟或伪造FindAll()方法以返回您想要的任何实体列表。