-
-
Notifications
You must be signed in to change notification settings - Fork 798
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
VerifyAll
throws System.InvalidOperationException: 'Nullable object must have a value.'
#711
Comments
@aeslinger0 - Thanks for reporting. It would be great if you could post a short, self-contained repro code example or unit test so this can be looked into. |
That's unrelated. It's simply because you've been debugging with a Moq assembly that's been built with the Release configuration. |
This should reproduce the problem: |
OK, after studying your ZIP file for a while, I think this is what you're dealing with: [Fact]
public void Test()
{
int? x = 1;
var mock = new Mock<Action<int?>>();
mock.Setup(m => m(x.Value));
mock.Object(1);
x = null;
mock.VerifyAll();
}
Will need to take a deeper look, but it does feel like a bug. |
On the other hand, what about the following test: int? x = 1;
var mock = new Mock<Action<int?>>();
-mock.Setup(m => m(x.Value));
-mock.Object(1);
x = null;
-mock.VerifyAll();
+mock.Verify(m => m(x.Value), Times.Never); This produces the same error, but in this case it's much more obvious why things are going wrong. Should this test succeed or not? I think this one should fail. |
After some more pondering I am pretty certain that this is a bug, because there is an internal inconsistency in such a setup: On the one hand, the argument expression gets evaluated eagerly to produce a constant-value argument matcher (used for matching invocations against setups), and on the other hand, the original setup expression gets reevaluated (i.e. lazily) during verification. That doesn't seem to make much sense. Verification should probably also use the eagerly evaluated argument value. |
Thanks. Based on your comments, I changed the test from:
To:
The test now passes. Thanks for your help. Good luck with the bug! |
Note to self, here's a related unit test; Moq does evaluate some things lazily by design: It might get quite tricky to correctly draw the line between eager and lazy evaluation of arguments in setup/verify expressions. |
The test mentioned in #711 (comment) no longer reproduces this problem in current [Fact]
public void Test()
{
int? x = 1;
var mock = new Mock<Action<int?>>();
+ mock.Setup(m => m(1));
mock.Setup(m => m(x.Value));
mock.Object(1);
x = null;
mock.VerifyAll();
} The problem occurs when Off the top of my head, I can think of two ways to fix this:
|
I'm running a unit test that passed using Moq 4.2.1409.1722 but now fails using 4.10.0 with the exception above. I loaded the symbols for Moq to see if I could figure out what was failing. This is what I saw:
Not sure if related, but note the error when trying to view the
expression
parameter: "Cannot obtain value of the local variable or argument because it is not available at this instruction pointer, possibly because it has been optimized away."I went up the call stack to see if
expression
was being passed in. I can see that expression had a value:I might be going down the wrong path, but to me it appears like something is causing that expression to disappear inside the call to
this.fnCanBeEvaluated(expression)
which I am unable to see inside of.So it might be a bug in Moq or, if it's a problem with my code, then Moq should probably check for the condition that causes the exception and throw an outer exception with a better description.
The text was updated successfully, but these errors were encountered: