实体框架核心FromSql模拟测试用例

时间:2019-05-10 05:30:32

标签: c# .net entity-framework-core

我正在使用带有获取存储过程调用的EF Core非实体模型。参见下面的示例代码

context.Query<ClassDTO>().FromSql("SpName @Param1, @Param2, @Param3", 
                                  new SqlParameter[] { param1, param2, param3 }).ToList();

代码工作正常。但是我需要编写模拟测试用例。

有人可以帮我吗?如何模拟Context.Query或如何为此代码编写测试用例?

我尝试实现以下方法:

https://nodogmablog.bryanhogan.net/2017/11/unit-testing-entity-framework-core-stored-procedures/

但它适用于  ** productContext.Products.MockFromSql(...)

但是对我来说,就像productContext.Query.MockFromSql()。因此,建议我如何编写测试用例。

谢谢。

西瓦

1 个答案:

答案 0 :(得分:0)

DbQuery<TQuery>设置的实际FromSql模拟与DbSet<TEntity>相同,因此OP链接是相关的(尽管这是所有实现,但是如果您需要在FromSql sql /参数,您需要进行其他模拟设置;警告:它很快就会变得难看)。

您需要使用可查询的序列模拟DbQuery<TQuery>,按照OP链接模拟查询提供程序(扩展了所需的任何特定模拟匹配),然后将DbQuery模拟对象分配给DbContext { {1}}方法和DbContext .Query<TQuery>()属性。

就模拟DbQuery而言,这就是我用来创建DbQuery的方法:

DbQuery<TQuery>

然后,如果我需要支持FromSql,我将提供程序更改为查询提供程序模拟(按照OP为CreateQuery设置的模拟):

public static Mock<DbQuery<TQuery>> CreateDbQueryMock<TQuery>(this DbQuery<TQuery> dbQuery, IEnumerable<TQuery> sequence) where TQuery : class {
    var dbQueryMock = new Mock<DbQuery<TQuery>>();

    var queryableSequence = sequence.AsQueryable();

    dbQueryMock.As<IAsyncEnumerableAccessor<TQuery>>().Setup(m => m.AsyncEnumerable).Returns(queryableSequence.ToAsyncEnumerable);
    dbQueryMock.As<IQueryable<TQuery>>().Setup(m => m.ElementType).Returns(queryableSequence.ElementType);
    dbQueryMock.As<IQueryable<TQuery>>().Setup(m => m.Expression).Returns(queryableSequence.Expression);
    dbQueryMock.As<IEnumerable>().Setup(m => m.GetEnumerator()).Returns(queryableSequence.GetEnumerator());
    dbQueryMock.As<IEnumerable<TQuery>>().Setup(m => m.GetEnumerator()).Returns(queryableSequence.GetEnumerator()); 
    dbQueryMock.As<IQueryable<TQuery>>().Setup(m => m.Provider).Returns(queryableSequence.Provider);

    return dbQueryMock;
}

如果您想节省一些时间,我最终将以上内容包装在一个库中:https://github.com/rgvlee/EntityFrameworkCore.DbContextBackedMock.Moq