简体   繁体   中英

Entity Framework Core FromSql mock test cases

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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