Open GoogleCodeExporter opened 8 years ago
You're getting that behaviour because the .Verify is executed and the method
calls
are matched against the machine state that exists *after* all the calls have
taken
place (and been recorded).
If you imagine what Moq recorded during execution, it *recorded* one call where
you
called Save() with your MyClass3 instance, and then made another call to Save()
with
your MyClass3 instance. (It's not really feasible for Moq to do a deep clone
of your
parameters, so it didn't record that your MyClass3 instance had one property
value at
the first call and a different value at the second call.)
Then when you come along and talk to it about 'calls to Save where the MyClass3
had
the desired property', then at that point, both calls match because right then,
the
(one) MyClass3 instance matches your constraint.
You might have better luck if you specified your constraint as a pre-call
.Setup.Verifiable() instead of using a post-call .Verify(). That's because the
match
is then run against the parameters as they happen rather than as they are when
you
call .Verify().
But unfortunately there's no overload of .Setup/.Verifiable() that takes a Times
object (as you use in .Verify). Without that, you end up with a setup that
checks
that it's called at least once, not exactly once:
// Not quite right - checks at least one matching call
myClass2Mock
.Setup(p => p.Save(It.Is<MyClass3>(m => m.MyProperty == expectedMyProperty)))
.Verifiable();
DoIt(myClass2Mock.Object);
myClass2Mock.Verify();
But fortunately there is a method '.AtMostOnce()' that you can call on a .Setup
result, which, in combination with .Verify() gives you 'precisely once'. But
unfortunately that's deprecated in favour of the Times objects on .Verify
calls...
which don't work in your case for the reasons stated above! :(
// Right - checks for precisely one matching call with state
// - but uses a deprecated call
myClass2Mock
.Setup(p => p.Save(It.Is<MyClass3>(m => m.MyProperty == expectedMyProperty)))
.AtMostOnce()
.Verifiable();
DoIt(myClass2Mock.Object);
myClass2Mock.Verify();
I've come across this particular issue before myself, where I've wanted to use a
strict mock to check that something happened, but wanted a constraint on the
count.
Perhaps arranging for the .Verifiable() method on ISetup<T> to take a Times
object
would solve both problems...
Original comment by RoystonS...@googlemail.com
on 6 Mar 2010 at 4:59
I agree that allowing Times to be passed in to a setup (maybe as an argument to
Verifiable?) would be good.
That would not solve the underlying inconsistency here between Verifiable and
Verify,
unfortunately :(
Original comment by kzu.net
on 8 Mar 2010 at 4:35
I'm thinking about un-deprecating the occurrence constraints on setups.
Thoughts?
Original comment by kzu.net
on 11 Aug 2010 at 4:59
Original issue reported on code.google.com by
joshuajr...@gmail.com
on 30 Jul 2009 at 4:45Attachments: