I have created the following extension method for an IQueryable to use it in Entity Framework DbContext moqs in unit tests
public static DbSet<T> BuildMockDbSet<T>(this IQueryable<T> source)
where T : class
{
var mock = new Mock<DbSet<T>>();
var sourceList = source.ToList();
mock.As<IDbAsyncEnumerable<T>>()
.Setup(x => x.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<T>(sourceList.GetEnumerator()));
mock.As<IQueryable<T>>()
.Setup(x => x.Provider)
.Returns(new TestDbAsyncQueryProvider<T>(source.Provider));
mock.As<IQueryable<T>>()
.Setup(x => x.Expression)
.Returns(source.Expression);
mock.As<IQueryable<T>>()
.Setup(x => x.ElementType)
.Returns(source.ElementType);
mock.As<IQueryable<T>>()
.Setup(x => x.GetEnumerator())
.Returns(sourceList.GetEnumerator());
mock.Setup(s => s.AsNoTracking()).Returns(mock.Object);
mock.Setup(x => x.Include(It.IsAny<string>())).Returns(mock.Object);
mock.Setup(x => x.FirstOrDefault(It.IsAny<Expression<Func<T,bool>>>())).Returns((Expression<Func<T,bool>> x) => sourceList.FirstOrDefault(x as Func<T,bool>));
mock.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) =>
{
sourceList.Add(s);
}).Returns((T v) => v);
return mock.Object;
}
The problem I am experiencing is that when I add a new item to it, i am adding it in fact to sourceList which is not the same object as source. So looping over the items should return the items of the sourceList.
For the FirstOrDefault method, this does not work however. I would like to simply get whatever predicate was given originally and pass that to the FirstOrDefault method of the sourceList. But I am unable to set this up correctly.
The exception message is only saying that what I do is invalid, not why nor how it should be.

FirstOrDefaultare implemented as extension methods which are notoriously "hard" to mock. "Hard" meaning: it's not supported by mocking frameworks.GetEnumerator()incorrectly by providing an instance. Use a delegate. Reference: stackoverflow.com/a/43998703/5233410 . I would also suggest casting the source if possible instead of trying to maintain separate lists/collections