Moq4: Possible regression between 4.7.49 and 4.7.58?

Created on 21 Jun 2017  路  5Comments  路  Source: moq/moq4

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:

```c#
///


/// Find All
///

[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);
    }

```

Most helpful comment

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.

All 5 comments

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

I have the same exact problem.

````csharp

[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

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.

@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.

Confirmed. It is fixed.
Thanks a lot.

Regards

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Jdsleppy picture Jdsleppy  路  6Comments

ohadschn picture ohadschn  路  4Comments

Astrophizz picture Astrophizz  路  5Comments

StasPerekrestov picture StasPerekrestov  路  4Comments

IFYates picture IFYates  路  3Comments