I have a piece of code like this (simplified):
await realApiClient.DoSomething(entity);
entity.Email = newEmail;
await realApiClient.DoSomethingElse(entity);
In my test I have created a fake and want to check that both DoSomething
and DoSomethingElse
were called. So I do it like this:
A.CallTo(() => fakeApiClient.DoSomething(A<Entity>
.That.Matches(p => p.Email == "[email protected]"
)))
.MustHaveHappenedOnceExactly();
A.CallTo(() => fakeApiClient.DoSomethingElse(A<Entity>
.That.Matches(p => p.Email != "[email protected]"
)))
.MustHaveHappenedOnceExactly();
The problem - the test for DoSomething
fails because FakeItEasy seems to not capture the full state of the method call arguments. When I check the email in DoSomething
call, FakeItEasy is checking against the value that was updated in entity.Email = newEmail;
and not the original value before the update.
As soon as I comment out entity.Email = newEmail;
then DoSomething
test succeeds. But then, of course, DoSomethingElse
rightfully fails because it expected the email to be changed.
What is the proper way to access the argument state as it actually was at the time when DoSomething
was called?
CodePudding user response:
FakeItEasy doesn't (and likely never will) store a snapshot of an object's state, for reasons discussed mostly in the accepted answer to MustHaveHappened fails when called twice on the same object and also in Verifying multiple method calls with reference parameters.
There are hints there about manually capturing important state to preserve it between calls.
In your simple example, though, one option might be to invoke a custom method in your "arrange" phase, having it capture the important parts of the argument. Something like
var capturedEmails = new List<String>();
A.CallTo(() => fakeApiClient.DoSomething(A<Entity>._))
.Invokes((Entity e) => capturedEmails.Add(e.Email));
…
await realApiClient.DoSomething(entity);
entity.Email = newEmail;
await realApiClient.DoSomethingElse(entity);
…
capturedEmails.Should().ContainExactly("[email protected]");
(not run nor even compiled but you get the gist)