-
-
Notifications
You must be signed in to change notification settings - Fork 794
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
NullReferenceException when calling Verify() on a mock of DbContext with a mocked Set<> property #464
Comments
Good question, I'll have to take a closer look at this. Until I do, let me say that there's ultimately the problem that Moq internally uses your mock's implementation of |
Hmm :/ Is there any way to get (or build) a debuggable version of the package? I tried checking out the repo but apparently my VS2017 won't load most of the csproj :/ I'll have to have a look at what's missing |
Sure, the Moq.sln really should be openable in VS 2017 without any special configuration. Can't say what goes wrong on your machine. Some notes:
Regarding the code questions you raised, the whole check against A good solution would be to change Moq such that this code path will never get executed by Moq's internals; the solution should NOT be (IMHO) to bolt on even more safeguards. In other words, it might be better to take away code instead of adding more. If you look into this, you're likely to stumble upon code paths that take you through I'll take a look at your repro code tomorrow, but please feel free to post back your own findings or to propose a fix! |
Thanks ! I'll try again to get a debug dll in order to reproduce it in place, then maybe try to produce a sscce to drop by. If I manage to get my hands on good intel, i'll bring the guns :) Thanks for your answers, I'll let you know if I find anything, maybe make a PR if I think I can fix it ^^ |
Here's the result I get with your repro code:
|
Hmmm I think the difference mainly comes from
Apparently, when the DbSet is not mocked I have this in the list of Invocations Performed :
And this only happens if i trigger the object creation through calling I don't know yet why those invocations are performed, but I'll bet those are the problem, as when Set is setup to return another mock's object it fails.
I have no problem with getting the expected result (VerifyException and "Expected invocation but was 0 times" etc.) I use :
EntityFramework is use in Code First mode with EnabledMigrations set to true but AutomaticMigrations set to false. the db context class looks like this:
I highly suspect the constructor calling |
I can't verify your suspicion right now, but whenever constructors get involved, it helps to remember that they might call virtual functions that you haven't yet set up. So it can be beneficial to delay mock instantiation as long as possible, so that you can finish configuring the mock before it gets invoked. For example:
Have you tried changing this to a lambda, i.e. |
I have the same error using |
Ah, about opening the solution: I am not using VS2017 as I thought I was. I am currently on VS2015 here, while I use 2017 at home. Guess I'll have to have a look there then. |
I finally found some time to take a slightly closer look at your repro code. You will see the behavior I reported (and which you expected to begin with) if you define public partial class MyDbContext : DbContext { } You'll get the behaviour you've reported when you define it like this instead:
If you updated to a more recent version of Moq, you'd get a slightly more useful error message instead of the one you posted above:
Basically, you can work around your issue by providing your // this forest of angle brackets and parentheses looks horrible, but makes things work:
var myEntities = new List<MyEntity>();
Mock<DbSet<MyEntity>> mockDbSet = new Mock<DbSet<MyEntity>>();
mockDbSet.As<IEnumerable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(() => myEntities.GetEnumerator());
mockDbSet.As<IEnumerable>().Setup(m => m.GetEnumerator()).Returns(() => myEntities.GetEnumerator()); I've seen more and more questions about mocking Entity Framework I'd be happy if you actually found a clean way to make Moq not invoke mocks' Please let me know how you would like to proceed. |
Ah, so it was the enumerator that was at fault. It did not even occur to me to replace I'd be more than happy to try and have a look at what can be done to bypass using Indeed, EntityFramework Anyway thanks for your time 👍 |
@Eregrith: You're welcome. Regarding testing and Entity Framework, I like the idea of the InMemory provider they've introduced in EF Core. As far as I can see, it means you no longer need to mock Yes, I'd say let's close this issue, and feel free to open a new one regarding Moq's internal use of a mock's Some background on that topic in preparation:
|
The call to Verify() raises a NullReferenceException when trying to format Performed Invocations with the following setup :
Contrary to what's expected (verify exception with a summary of performed invocations), I have a NullReferenceException :
I managed to browse the code here and locate the place of the alleged error :
https://github.com/moq/moq4/blob/61c35056dda76a157dd78cd9578cee86f7a16f02/Source/Extensions.cs#L91-L100
Apparently the
Select
triggers the cast and takesenumerable.Cast<object>().Take(maxCount + 1);
andobjs.Take(maxCount)
.Note the inconspicuous comment just two lines above:
Is it possible that is the value is mocked (which it is), the check on
GetEnumerator()
is not enough ?Just out of curiosity (and despair) I tried to set it up like this:
But I have exactly the same exception, so I don't know if the mock's enumerable's implementation is at fault
The text was updated successfully, but these errors were encountered: