Mock AsNoTracking Entity Framework
c#, entity-framework, mocking, moq, unit-testing
Solution
Looking at the source code of the `AsNoTracking()` extension method:
public static IQueryable AsNoTracking(this IQueryable source)
{
var asDbQuery = source as DbQuery;
return asDbQuery != null ? asDbQuery.AsNoTracking() : CommonAsNoTracking(source);
}
Since `source` (your `DbSet<Product>` you're trying to mock) is indeed a `DbQuery` (because `DbSet` is deriving from `DbQuery`), it tries to invoke the 'real' (non-mocked) `AsNoTracking()` method which rightfully returns null.
Try to mock the `AsNoTracking()` method as well:
mockSet.Setup(x => x.AsNoTracking()).Returns(mockSet.Object);
Problem
How do I mock AsNoTracking method? In below example, DbContext has injected to the service class.It works fine if I remove AsNoTracking extension method from GetOrderedProducts method, but with AsNoTracking test fails because it returns null. I've also tried to mock AsNoTracking to return proper value but it didn't work. ``` public interface IUnitOfWork { IDbSet<TEntity> Set<TEntity>() where TEntity : class; int SaveAllChanges(); } public class Entites : DbContext, IUnitOfWork { public virtual DbSet<Product> Products { get; set; } // This is virtual because Moq needs to override the behaviour public new virtual IDbSet<TEntity> Set<TEntity>() where TEntity : class // This is virtual because Moq needs to override the behaviour { return base.Set<TEntity>(); } public int SaveAllChanges() { return base.SaveChanges(); } } public class ProductService { private readonly IDbSet<Product> _products; private readonly IUnitOfWork _uow; public ProductService(IUnitOfWork uow) { _uow = uow; _products = _uow.Set<Product>(); } public IEnumerable<Product> GetOrderedProducts() { return _products.AsNoTracking().OrderBy(x => x.Name).ToList(); } } [TestFixture] public class ProductServiceTest { private readonly ProductService _productService; public ProductServiceTest() { IQueryable<Product> data = GetRoadNetworks().AsQueryable(); var mockSet = new Mock<DbSet<Product>>(); mockSet.As<IQueryable<Product>>().Setup(m => m.Provider).Returns(data.Provider); mockSet.As<IQueryable<Product>>().Setup(m => m.Expression).Returns(data.Expression); mockSet.As<IQueryable<Product>>().Setup(m => m.ElementType).Returns(data.ElementType); mockSet.As<IQueryable<Product>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); var context = new Mock<Entites>(); context.Setup(c => c.Products).Returns(mockSet.Object); context.Setup(m => m.Set<Product>()).Returns(mockSet.Object); context.Setup(c => c.Products.AsNoTracking()).Returns(mockSet.Object); _productService = new ProductService(context.Object); } private IEnumerable<Product> GetRoadNetworks() { return new List<Product> { new Product { Id = 1, Name = "A" }, new Product { Id = 2, Name = "B" }, new Product { Id = 1, Name = "C" } }; } [Test] public void GetOrderedProductTest() { IEnumerable<Product> products = _productService.GetOrderedProducts(); List<string> names = products.Select(x => x.Name).ToList(); var expected = new List<string> {"A", "B", "C"}; CollectionAssert.AreEqual(names, expected); } } ``` The problem is AsNoTracking returns null in unit test