DbSet mock, no results while calling ToList secondly

后端 未结 4 1493
情深已故
情深已故 2020-12-15 06:29

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

相关标签:
4条回答
  • 2020-12-15 06:33

    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

    0 讨论(0)
  • 2020-12-15 06:42

    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 :)

    0 讨论(0)
  • 2020-12-15 06:50

    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() );
    
    0 讨论(0)
  • 2020-12-15 06:55

    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();
    
    0 讨论(0)
提交回复
热议问题