I\'m trying to mock DbContext and DbSet. This works for my previous unit tests, but problem occurs while my code was calling ToList method on DbSet second time.
Firs
I just wanted to added to Wiktor Zychla's answer my little part. If someone is looking for Async version of this mock (coming from this tutorial: http://msdn.microsoft.com/en-us/data/dn314429.aspx#async) then this is my modification to TestDbAsyncEnumerator<T>
class:
internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T>
{
private readonly IEnumerator<T> _inner;
public TestDbAsyncEnumerator(IEnumerator<T> inner)
{
_inner = inner;
}
public TestDbAsyncEnumerator(Func<IEnumerator<T>> valueFunction)
{
_inner = valueFunction();
}
public void Dispose()
{
_inner.Dispose();
}
public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
{
return Task.FromResult(_inner.MoveNext());
}
public T Current
{
get { return _inner.Current; }
}
object IDbAsyncEnumerator.Current
{
get { return Current; }
}
}
Then like Wiktor suggested you have to setup it with delegate so in case of async it would be like that:
mockSet.As<IDbAsyncEnumerable<Blog>>()
.Setup(m => m.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<Blog>(() => data.GetEnumerator()));
If someone wants source for that then here you go: https://github.com/kelostrada/EntityFrameworkWithMock.Test
I can't comment on Wiktor's post as I haven't got enough reputation, but i would like to add a little extra to Wiktor's answer.
The code
mockSet.Setup((m => m.GetEnumerator()).Returns(() => data.GetEnumerator())
Will fail if you give it a zero argument lambda like in the example(At least the version I am using). Passing an argument that is never used will allow it to meet the signature requirement however.
mockSet.Setup((m => m.GetEnumerator()).Returns(x => data.GetEnumerator())
Will compile however, and works as expected.
And this also applies to Kelu's answer as well (Although he has added the lambda in the wrong place.
mockSet.As<IDbAsyncEnumerable<Blog>>()
.Setup(m => m.GetAsyncEnumerator())
.Returns(x => new TestDbAsyncEnumerator<Blog>(data.GetEnumerator()));
Not trying to nitpick answers here, i'm just adding because i made these mistakes myself :)
You return the very same enumerator instance upon each call to GetEnumerator
. When it enumerates once, it is done, EF doesn't call its Reset
method, rather it asks for a new enumerator.
But you return the one that just has yielded all elements and yields no more.
Instead, return a function that returns the enumerator, that will return a new enumerator each time you ask for it.
q.Setup(m => m.GetEnumerator()).Returns( () => queryableData.GetEnumerator() );
If you put a "Where" clause before the .ToList() call, the data should remain present.
var a1 = dbset.Where(m => m != null).ToList();
var a2 = dbset.Where(m => m != null).ToList();