5

I have a Moq DbSet that has been working until recently, however since the last update of dependencies it keeps throwing a NotImplementedException on IQueryable.Provider

Code used as follows:

var mockSet = new Mock<DbSet<A>>();
var list = new List<A>();
var queryable = list.AsQueryable();
mockSet.As<IQueryable<A>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockSet.As<IQueryable<A>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockSet.As<IQueryable<A>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockSet.As<IQueryable<A>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());

var f =mockSet.Object.FirstOrDefault(); // NotImplementedException thrown here

The exception thrown as follows:

System.NotImplementedException
The member 'IQueryable.Provider' has not been implemented on type
'DbSet`1Proxy_1' which inherits from 'DbSet`1'.
Test doubles for 'DbSet`1' must provide implementations of methods
and properties that are used.
Kanadaj
  • 962
  • 9
  • 25
  • 1
    This Microsoft article provides an implementation to allow you to use in-memory test doubles. I have just updated my Moq 4.7.99 and Castle.Core 4.1.1 and my tests are passing. https://msdn.microsoft.com/en-us/library/dn314431(v=vs.113).aspx – Jasen Sep 15 '17 at 17:57
  • That's very helpful. Sadly, I often find that the more advanced MSDN articles are basically just dumbed into a massive list. – Kanadaj Sep 15 '17 at 20:02
  • Using `Sqlite` in memory database will provide better testing experience, since you don't be bounded to how you build your query. Just insert required data, run your query, check expected result – Fabio Dec 28 '17 at 21:25

2 Answers2

4

Chances are that you have been using version 4.7.58 of Moq. That particular version was affected by a regression that would have triggered such a NotImplementedException. That regression has been fixed in version 4.7.63, so I suggest you update your Moq package reference to version 4.7.63 or newer to resolve this issue.

The fact that your code would have worked in Moq versions before 4.7.58 was due to a "feature" which unfortunately caused a lot more problems than it solved. For this reason, that feature was reverted.

Moq has been brought back to its original behaviour, where, in this particular scenario, you need to set up the various interface members via mock.As<TInterface> before the call to mock.Object. (Usually, in Moq, it's perfectly fine to perform more set ups even after retrieving the mock object; this scenario is a notable exception. Hopefully this can be fixed in a future version of Moq.)

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
  • Does this mean that I have to basically use mock.As().Object in this scenario? Based on my Git history, the issue happened with Moq 4.7.99 and Castle.Core 4.1.1.0 with the code exactly as provided above. – Kanadaj Sep 17 '17 at 14:10
  • After updating from 4.7.25 to 4.7.99, the issue is happening again. – Kanadaj Sep 17 '17 at 14:15
  • @DanielRusznyak: Given the code you posted above, and using Moq 4.7.99, I cannot reproduce the error that you say you're seeing. It compiles and runs without any errors. Are you sure that you haven't omitted anything in your repro code? What version of Entity Framework are you targeting? – stakx - no longer contributing Sep 17 '17 at 15:10
  • Actually, after looking into it, the issue was a stray `mock.Object.Add()` call before the setup of the Provider, which threw an error in a completely different place The old version ignored this problem, however the new versions fail on the next `mock.Object.FirstOrDefault()` with a `NotImplementedException` without pointing out the real issue. – Kanadaj Sep 17 '17 at 16:18
  • Re: _"the issue was a stray mock.Object.Add() call before the setup_" - Yep, as per the 3rd paragraph that would be it. Re: _"the old version ignored this problem"_ - it didn't ignore it; in fact, the problematic feature I mention in the 2nd paragraph of my answer was exactly what enabled an early `mock.Object` call to work in EF tests (at the expense of breaking tons of other equally likely use cases). – stakx - no longer contributing Sep 17 '17 at 16:46
0

Rolling back Castle.Core to 4.0.0 and Moq to the latest version supporting 4.0.0 solved the issue. I'm still wondering if there is something I've missed that would fix this problem in the new version.

Kanadaj
  • 962
  • 9
  • 25