Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible regression between 4.7.49 and 4.7.58? #383

Closed
sharky98 opened this issue Jun 21, 2017 · 5 comments
Closed

Possible regression between 4.7.49 and 4.7.58? #383

sharky98 opened this issue Jun 21, 2017 · 5 comments

Comments

@sharky98
Copy link

I've created a piece of code, based on article Entity Framework Testing with a Mocking Framework (EF6 onwards). Where I'm bugging is in the Testing query scenarios section.

I was using version 4.7.49 and I had to modify the mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(0 => data.GetEnumerator()); to mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); to make it work. The test was running fine. When I updated Moq to 4.7.58, the test is failing with following error:

Message: Test method TestSuites.Models.TypeTests.FindAll threw exception:
System.NotImplementedException: The member 'IEnumerable.GetEnumerator' has not been implemented on type 'DbSet1Proxy' which inherits from 'DbSet1'. Test doubles for 'DbSet`1' must provide implementations of methods and properties that are used.

I'm new to the C#, ASP.NET MVC, EF world, so I'm a bit lost on where to look for my error.

Here my test method, if that make any differences:

        /// <summary>
        /// Find All
        /// </summary>
        [TestMethod]
        public void FindAll()
        {
            // Mocking the set and context
            // [...]

            // Create fake data
            IQueryable<Type> data = new List<Type>
            {
                new Type { TypeId= 1, Name = "Test A", Slug = "test-a", Format = "dollar" },
                new Type { TypeId= 2, Name = "Test B", Slug = "test-b", Format = "percent" },
                new Type { TypeId= 3, Name = "Test C", Slug = "test-c", Format = "dollar" },
            }.AsQueryable();

            // Setup the IQueryable on the mockRateTypeSet
            mockTypeSet.As<IQueryable<RateType>>().Setup(m => m.Provider).Returns(data.Provider);
            mockTypeSet.As<IQueryable<RateType>>().Setup(m => m.Expression).Returns(data.Expression);
            mockTypeSet.As<IQueryable<RateType>>().Setup(m => m.ElementType).Returns(data.ElementType);
            mockTypeSet.As<IQueryable<RateType>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

            // Find all
            List<Type> types = typeRepository.FindAll().ToList();

            // Asserts
            Assert.AreEqual(3, rateTypes.Count());
            Assert.AreEqual("Test Rate A", rateTypes[0].Name);
            Assert.AreEqual("Test Rate B", rateTypes[1].Name);
            Assert.AreEqual("Test Rate C", rateTypes[2].Name);
        }
@stakx
Copy link
Contributor

stakx commented Jun 21, 2017

Thanks for reporting. I would like to look into this to see what other use cases might be affected.

Unfortunately, I cannot get your repro code to run, since some type declarations and variable definitions are missing. Could you please provide a short but complete repro code? Thanks!

(Btw. this sounds slightly reminiscent of #22.)

@vascofernandes
Copy link

vascofernandes commented Jun 21, 2017

I have the same exact problem.

    [TestClass]
    public class Test
    {
        public class Post
        {
            public string Url { get; set; }
        }

        public interface IBlogContext
        {
            IDbSet<Post> Posts { get; }
        }

        private static Mock<DbSet<T>> CreateMockSet<T>(IQueryable<T> dataForDbSet) where T : class
        {
            var dbsetMock = new Mock<DbSet<T>>();

            dbsetMock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(dataForDbSet.Provider);
            dbsetMock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(dataForDbSet.Expression);
            dbsetMock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(dataForDbSet.ElementType);
            dbsetMock.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(dataForDbSet.GetEnumerator());
            return dbsetMock;
        }

        [TestMethod]
        public void TestGetFirst()
        {
            var posts = Enumerable.Range(0, 5).Select(x => new Post()
            {
                Url = string.Format("www.someurl{0}", x)
            }).AsQueryable();

            var dbsetMock = CreateMockSet(posts);

            var mockContext = new Mock<IBlogContext>();
            mockContext.Setup(c => c.Posts).Returns(dbsetMock.Object);

            mockContext.Object.Posts.First().Url.Should().Be("www.someurl0");
        }
    }

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

Regards

@stakx
Copy link
Contributor

stakx commented Jun 21, 2017

Thank you @vascofernandes for the repro code.

This is indeed a regression introduced by #381 (which itself fixed a major regression that has been lurking around for ages).

I expect to have a fixed version of Moq available later today, or during the next few days at the latest.

@stakx
Copy link
Contributor

stakx commented Jun 21, 2017

@vascofernandes, your reported issue should be fixed in Moq 4.7.63.

@sharky98: If you find that the latest version doesn't resolve your problem, please report back.

@stakx stakx closed this as completed Jun 21, 2017
@vascofernandes
Copy link

Confirmed. It is fixed.
Thanks a lot.

Regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants