简体   繁体   English

Mocking DbContext 与 NSubstitute 和 Repository 为空或 NotImplementedException

[英]Mocking DbContext with NSubstitute and Repository is empty or NotImplementedException

I'm trying to mock my DbContext class to do unit tests with NSubstitute but I cannot recover this data from my fake dbcontext through the repository class.我正在尝试模拟我的 DbContext class 以使用 NSubstitute 进行单元测试,但我无法通过存储库 class 从我的假 dbcontext 中恢复这些数据。

I have a generic class (SubstituteDbContext) to create sobe DbSet's and set them to the respective DbSet property in my DbContext.我有一个通用的 class (SubstituteDbContext) 来创建 sobe DbSet 并将它们设置为我的 DbContext 中的相应 DbSet 属性。

I have the code below for each property in DbContext that I want to mock:对于要模拟的 DbContext 中的每个属性,我都有以下代码:

var data = DbSetData.MyData();
var dbSet = SubstituteDbContext.DbSet(data);
dbContext.MyObject.Returns(dbSet);

I create a DbSet to every property with the method below:我使用以下方法为每个属性创建一个 DbSet:

public static DbSet<T> getDbSet<T>(IEnumerable<T> data = null)
    where T : class
{
    var dbSet = Substitute.For<DbSet<T>, IQueryable<T>>();

    if (data != null)
    {
        var queryable = data.AsQueryable();
        ((IQueryable<T>)dbSet).Provider.Returns(queryable.Provider);
        ((IQueryable<T>)dbSet).Expression.Returns(queryable.Expression);
        ((IQueryable<T>)dbSet).ElementType.Returns(queryable.ElementType);
        ((IQueryable<T>)dbSet).GetEnumerator().Returns(queryable.GetEnumerator());
        ((IQueryable<T>)dbSet).AsNoTracking().Returns(queryable);
    }
    return dbSet;
}

And in my BaseRepository class (my abstract-parent class for every repository) I have some methods like below to get data:在我的 BaseRepository class (每个存储库的我的抽象父 class )我有一些如下方法来获取数据:

public virtual IEnumerable<T> List(Expression<Func<T, bool>> predicate)
{
    return DbContext.Set<T>()
        .Where(predicate)
        .AsEnumerable();
}

But when my debugger runs the List method of BaseRepository I have two possible results (because I tried some variations of the code above):但是当我的调试器运行 BaseRepository 的 List 方法时,我有两个可能的结果(因为我尝试了上面代码的一些变体):

1º I've got System.NotImplementedException
2º The result returned is empty (but 

Your SUT invokes DbContext.Set<T>() however you only set up dbContext.MyObject.Returns(dbSet) .您的 SUT 调用DbContext.Set<T>()但是您只设置dbContext.MyObject.Returns(dbSet) You'll need to set up the former.您需要设置前者。

Like @rgvlee said I wasn't setting up DbSet correctly.就像@rgvlee 说我没有正确设置 DbSet 一样。

I've changed my getDbSet<T> generic method for setDbSet<T> because I'm not returning the mocked DbSet anymore and setting it im DbContext in my another generic method with SetValue (from reflection).我已经更改了 setDbSet<T> 的setDbSet<T> getDbSet<T>泛型方法,因为我不再返回模拟的 DbSet 并在我的另一个泛型方法中使用 SetValue(来自反射)将其设置为 im DbContext。

Now I'm setting up the generic Set<T> property from my mocked DbContext directly in setDbSet<T> method and isn't necessary to set it directly with reflection.现在我直接在setDbSet<T>方法中从我的模拟 DbContext 设置通用Set<T>属性,并且不需要直接使用反射设置它。

Below the code from the new setDbSet<T>() (that was getDbSet<T>() ):在新setDbSet<T>()的代码下方(即getDbSet<T>() ):

public static void setDbSet<T>(DbContext dbContext, IEnumerable<T> data = null)
    where T : class
{
    var dbSet = Substitute.For<DbSet<T>, IQueryable<T>>();

    if (data != null)
    {
        var queryable = data.AsQueryable();
        ((IQueryable<T>)dbSet).Provider.Returns(queryable.Provider);
        ((IQueryable<T>)dbSet).Expression.Returns(queryable.Expression);
        ((IQueryable<T>)dbSet).ElementType.Returns(queryable.ElementType);
        ((IQueryable<T>)dbSet).GetEnumerator().Returns(queryable.GetEnumerator());
        ((IQueryable<T>)dbSet).AsNoTracking().Returns(queryable);
    }

    dbContext.Set<T>().Returns(dbSet);
}

And In my generic method that calls setDbSet<T>() I've removed the line below where I was setting up that mocked dbSet returned from getDbSet<T>() in my DbContext.在我调用setDbSet<T>()的通用方法中,我删除了下面的行,我在 DbContext 中设置从getDbSet<T>()返回的模拟 dbSet。

propertyInfo.SetValue(dbContext, dbSet);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM