Reputation: 1
I am using EF Core non-entity model with get stored procedure calling. See below sample code
context.Query<ClassDTO>().FromSql("SpName @Param1, @Param2, @Param3",
new SqlParameter[] { param1, param2, param3 }).ToList();
Code is working fine. But I need to write mock test cases.
Can anyone help me out? How to mock Context.Query
or how to write test cases for this code?
I tried to implement the follow way:
https://nodogmablog.bryanhogan.net/2017/11/unit-testing-entity-framework-core-stored-procedures/
But it will work for ** productContext.Products.MockFromSql(...)
But for me It is Like productContext.Query.MockFromSql(). So advice me how to write test cases.
Thanks in advance.
A Siva
Upvotes: 0
Views: 3551
Reputation: 3193
The actual FromSql mock set up for a DbQuery<TQuery>
is the same as a DbSet<TEntity>
so the OP link is relevant (although it's a catch all implementation, if you need to match on the FromSql sql/parameters you'll need to do additional mock set up; warning: it gets ugly quickly).
You need to mock the DbQuery<TQuery>
with a queryable sequence, mock the query provider as per the OP link (extended with any specific mock matching that you need) and then assign the DbQuery mocked object to BOTH the DbContext .Query<TQuery>()
method and the DbContext DbQuery<TQuery>
property.
In terms of mocking a DbQuery, this is what I use to create one:
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;
}
Then if I need to support FromSql I change the provider to a query provider mock (as per the OP the mock set up for CreateQuery):
mock.As<IQueryable<TEntity>>().Setup(m => m.Provider).Returns(queryProviderMock.Object);
I ended up wrapping the above in a library if you want to save yourself some time: https://github.com/rgvlee/EntityFrameworkCore.Testing
Upvotes: 1