Skip to content
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

Modify object captured by invocation impact the Verify #756

Closed
lepijohnny opened this issue Feb 21, 2019 · 2 comments
Closed

Modify object captured by invocation impact the Verify #756

lepijohnny opened this issue Feb 21, 2019 · 2 comments

Comments

@lepijohnny
Copy link
Contributor

lepijohnny commented Feb 21, 2019

Hi,

I found one strange behavior. The problem is that underlying invocation has been changed. Then

This is reproduction code...

public class Foo
{
	public bool AmIRealFoo { get; set; }
}

public interface IBar
{
	void Bar(Foo f);
}

var mock = new Mock<IBar>();

var foo = new Foo{AmIRealFoo = true};
mock.Object.Bar(foo);
foo.AmIRealFoo = false;

mock.Verify(m => m.Bar(It.Is<Foo>(f => f.AmIRealFoo)), Times.Once); //fails
mock.VerifyAll(); //pass

Expected behavior is that both VerifyAll and Verify pass.

@stakx
Copy link
Contributor

stakx commented Feb 21, 2019

This is a misunderstanding on your part. Moq does the right thing here.

Arguments are compared using Equals. Because Foo is a reference type, all that gets recorded for your mock.Object.Bar(foo); call is a reference to the foo instance, and not its state!

Your mock.Verify fails because verification looks at all invocations that happened, and passes each through the criteria given: It takes the recorded call to Bar(foo) and passes the foo instance through It.Is<Foo>(f => f.AmIRealFoo). Because foo.AmIRealFoo is false by that time, the criterion is false, therefore that invocation is not matched to your verification expression. Since there are no further recorded invocations, Verify did not find one invocation matching your expression, thus the verification error.

mock.VerifyAll succeeds because it checks whether all setups on mock have been invoked at least once. Since there are no setups at all, there is no failure here and the verification succeeds.

@stakx stakx closed this as completed Feb 21, 2019
@lepijohnny
Copy link
Contributor Author

lepijohnny commented Feb 21, 2019

@stakx - It perfectly makes sense if you don't have setup but actually it will fail even if you have setup as, you explained that as well, Verify acts purely on invocation and VerifyAll acts on setups.

var mock = new Mock<IBar>();
mock.Setup(m => m.Bar(It.IsAny<Foo>()));
var foo = new Foo{AmIRealFoo = true};
mock.Object.Bar(foo);
foo.AmIRealFoo = false;

mock.Verify(m => m.Bar(It.Is<Foo>(f => f.AmIRealFoo)), Times.Once); //fails
mock.VerifyAll(); //pass

Thanks for your clarification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants