I'm trying to create a mock for my IRepository
interface:
public interface IRepository<T> : ICollection<T>, IQueryable<T>
{
}
With this implementation:
public class RepositoryFake<T> : List<T>, IRepository<T>
{
public Expression Expression
{
get
{
return this.AsQueryable().Expression;
}
}
public Type ElementType
{
get
{
return this.AsQueryable().ElementType;
}
}
public IQueryProvider Provider
{
get
{
return this.AsQueryable().Provider;
}
}
}
But when I use it, I'm getting StackOverflow
exception. How to implement this interface correctly to be able to use just a List
as a repository?
Usage is very simple
[Test]
public void Test()
{
RepositoryFake<User> users = new RepositoryFake<User>();
users.Add(new User());
List<User> list = (from user in users
where user.Id == "5"
select user).ToList();
Assert.That(list, Is.Empty);
}
Here is screenshot of exception:
The reason for your problem is that if you perform AsQueryable
it checks if the object already implements IQueryable
and if yes returns it.
Use new EnumerableQuery<T>(this)
instead of AsQueryable
which doesn't perform this check.
Workaround for .net 3.5:
return ((IEnumerable<T>)this).Select(x=>x).AsQueryable()
First casts to IEnumerable<T>
so the chosen Select
method will be Enumerable.Select
not Queryable.Select
. The identity select will then return a new object that does not implement IQueryable<T>
, so the check if it's implemented in AsQueryable
fails.