Mocking DbSet<T>.FromSqlRaw in EF Core 5

Viewed 1018

On of the repository methods happens to use FromSqlRaw to fetch the data from SQL Server via a stored procedure.

I am trying to write unit test around it but no luck so far.

This is a sample snippet of how far I got

var fixture = new Fixture();
var context = new Mock<IMyDbContext>();
var dbSet = new Mock<DbSet<MyEntity>>();
            
var data = fixture.Build<MyEntity>().CreateMany().AsQueryable();
dbSet.As<IQueryable<MyEntity>>().Setup(m => m.Provider).Returns(data.Provider);
dbSet.As<IQueryable<MyEntity>>().Setup(m => m.Expression).Returns(data.Expression);
dbSet.As<IQueryable<MyEntity>>().Setup(m => m.ElementType).Returns(data.ElementType);
dbSet.As<IQueryable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
context.Setup(c => c.Set<MyEntity>()).Returns(dbSet.Object);

var repository = new MyRepository(context.Object);
 
var result = await repository.GetData();

Bit I got stuck with the following exception

System.InvalidCastException : Unable to cast object of type 'System.Linq.Expressions.ConstantExpression' to type 'Microsoft.EntityFrameworkCore.Query.QueryRootExpression'

The project uses EF Core 5.

Any idea how to solve this cast exception?

1 Answers

Don't mock IQueryable--you're just asking for a world of pain. Use a mock repository (possibly backed by an in-memory DbContext) to unit test consuming classes. Add some integration tests to verify your real repository implementation.

See Testing code that uses EF Core in the docs for more details.

Related