I'm trying to Mock the where clause of the dbset of my generic repository, and no idea why I'm getting a System.NotSupported Exception. I'm quite new into mocking, so I have no clue why this is happening.
private List<StubEntity> _data;
private Repository<StubEntity> _repository;
[TestInitialize]
public void TestInitialize()
{
    _data = new List<StubEntity>
    {
        new StubEntity {Id = 1, Name = "Entity 1"},
        ...
    };
    var queryableData = _data.AsQueryable();
    var mockDbSet = new Mock<DbSet<StubEntity>>();
    mockDbSet
        .Setup(m => m.Where(It.IsAny<Expression<Func<StubEntity, bool>>>()))
        .Returns<Expression<Func<StubEntity, bool>>>(p => queryableData.Where(p));
    var context = new Mock<StubContext>();
    context.Setup(x => x.DbEntities).Returns(mockDbSet.Object);
    context.Setup(x => x.Set<StubEntity>()).Returns(mockDbSet.Object);
    _repository = new Repository<StubEntity>(context.Object);
}
I'm only testing the where clause into a test
[TestMethod]
public void Find_ReturnsProperEntity()
{
    var entity = _repository.Find(s => s.Id == 1);
    ....
}
where the Find method just call the where clause of the context.
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
    return Context.Set<TEntity>().Where(predicate);
}
                Moq has issues with non-virtual members (methods/properties) and will throw exceptions when they are encountered.
eg:
System.NotSupportedException: System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: x => x.DbEntities.
The assumption here is that your StubContext looks something like this...
public class StubContext : DbContext {
    //...code removed for brevity
    public DbSet<StubEntity> DbEntities { get; set; }
    //...other code removed for brevity
}
...when it should be edited with a virtual property like...
public class StubContext : DbContext {
    //...code removed for brevity
    public virtual DbSet<StubEntity> DbEntities { get; set; }
    //...other code removed for brevity
}
Using the following utility classes
using Moq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
public static class MockDbSet {
    public static Mock<DbSet<T>> Create<T>(params T[] elements) where T : class {
        return elements.AsDbSetMock();
    }
}
public static class MockDbSetExtensions {
    public static Mock<DbSet<T>> AsDbSetMock<T>(this IEnumerable<T> list) where T : class {
        IQueryable<T> queryableList = list.AsQueryable();
        Mock<DbSet<T>> dbSetMock = new Mock<DbSet<T>>();
        dbSetMock.As<IQueryable<T>>().Setup(x => x.Provider).Returns(queryableList.Provider);
        dbSetMock.As<IQueryable<T>>().Setup(x => x.Expression).Returns(queryableList.Expression);
        dbSetMock.As<IQueryable<T>>().Setup(x => x.ElementType).Returns(queryableList.ElementType);
        dbSetMock.As<IQueryable<T>>().Setup(x => x.GetEnumerator()).Returns(() => queryableList.GetEnumerator());
        return dbSetMock;
    }
}
I recreated your unit test with a mocked DbSet and the suggested fix...
[TestClass]
public class MockDbSetTests {
    private List<StubEntity> _data;
    private Repository<StubEntity> _repository;
    [TestInitialize]
    public void TestInitialize() {
        _data = new List<StubEntity>
        {
            new StubEntity {Id = 1, Name = "Entity 1"},
            //...
        };
        var mockDbSet = _data.AsDbSetMock();
        var context = new Mock<StubContext>();
        context.Setup(x => x.DbEntities).Returns(mockDbSet.Object);
        context.Setup(x => x.Set<StubEntity>()).Returns(mockDbSet.Object);
        _repository = new Repository<StubEntity>(context.Object);
    }
    [TestMethod]
    public void Find_Should_Return_Proper_Entity() {
        //Act
        var entity = _repository.Find(s => s.Id == 1);
        //Assert
        Assert.IsNotNull(entity);
        Assert.IsTrue(entity.Count() == 1);
    }
}
...and it passed (GREEN).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With