简体   繁体   中英

moq.As<>().Setup() does not seem to work after getting moq.Object

I've derived a small test from Microsoft article on testing EF with moq: Testing with a mocking framework

namespace TestingDemo
{
    public class BloggingContext : DbContext
    {
        public virtual DbSet<Blog> Blogs { get; set; }
    }

    public class Blog
    {
        public string Name { get; set; }
    }

    [TestClass]
    public class QueryTests
    {
        [TestMethod]
        public void Test()
        {
            var data = new List<Blog> { new Blog { Name = "AAA" } }.AsQueryable();
            var mockSet = new Mock<DbSet<Blog>>();
            //var a = mockSet.Object;
            mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
            mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
            mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
            mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
            var b = mockSet.Object.ToList();
        }
    }
}

It works fine until I uncomment the line var a = mockSet.Object;After this I end up with exception on the line var b = mockSet.Object.ToList();

System.NotImplementedException: 'The member 'IEnumerable.GetEnumerator' has not been implemented on type 'DbSet`1Proxy' which inherits from 'DbSet`1'. Test doubles for 'DbSet`1' must provide implementations of methods and properties that are used.'

Am i missing something?

UPD: Using Moq 4.10.1, EF 6.2.0, VS Community 2019 16.6.1, .NET 4.7.2

You actually need to create DbContext mock as well like:

var context = new Mock<BloggingDbContext>();

var mockSet = new Mock<DbSet<Blog>>();

 mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
 mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
 mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
 mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

context.Setup(c => c.Blogs).Returns(mockSet.Object);

var blogs = context.Object.Blogs.ToList(); // usage 

The problem is you are adding the IQueryable<T> setups after you have obtained an instance of the mocked object ( mockSet.Object ); it won't work and that's also why it works fine once you comment out the assignment to a . You should only retrieve the mocked object once you have added setups for the behaviour you want to consume.

Interestingly once you have added those setups you can change them (override using another setup) at any time. You've just got to do the initial registration prior to retrieving the mocked object. I do it all the time with my system mock libraries.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM