Reputation: 4645
I experience some strange problems with FakeItEasy.
Imagine following unit test method:
[TestMethod]
public void DeletePerson_WhenCalled_ThenPersonIsDeleted()
{
const int personId = 24;
var commonParam = new CommonParam();
this.testee.DeletePerson(commonParam, personId );
A.CallTo(() => this.personRepository.DeletePersons(commonParam, new[] {personId }, false)).MustHaveHappened(Repeated.Exactly.Once);
A.CallTo(() => this.personRepository.SaveChanges()).MustHaveHappened(Repeated.Exactly.Once);
}
The testee.DeletePerson
-method looks like this:
public ResultatModel DeletePerson(CommonParam commonParam, int personId )
{
this.personRepository.DeletePersons(commonParam, new[] { personId });
this.personRepository.SaveChanges();
}
And the personRepository.DeletePersons
(but this one is faked by fakeiteasy...):
public void DeletePersons(CommonParam commonParam, IEnumerable<int> ids, bool hardRemove = false)
{
var persons = Entities.per_person.Where(e => ids.Contains(e.personId)
&& (e.accountId == null || e.accountId == commonParam.AccountId)).ToList();
if (hardRemove)
{
Entities.per_person.RemoveRange(persons);
}
else
{
persons.ForEach(person =>
{
person.geloescht = true;
person.mutationsBenutzer = commonParam.DbIdent;
person.mutationsDatum = DateTime.Now;
});
}
}
This is the reason why the test fails
Test method DataService.Test.PersonServiceTest.DeletePerson_WhenCalled_ThenPersonIsDeleted threw exception: FakeItEasy.ExpectationException:
Assertion failed for the following call: RepositoryContract.IPersonRepository.DeletePersons(commonParam: Commons.CommonParam, ids: System.Int32[], hardRemove: False) Expected to find it exactly once but found it #0 times among the calls: 1: RepositoryContract.IPersonRepository.RequestInfo = Faked Commons.Session.RequestInfo 2: RepositoryContract.IPersonRepository.DeletePersons( commonParam: Commons.CommonParam, ids: System.Int32[], hardRemove: False) 3: RepositoryContract.IPersonRepository.SaveChanges()
Why does the test fail?
Is the new[] { ... }
a problem?
Thanks in advance
Upvotes: 2
Views: 2341
Reputation: 32445
Is the new[] { ... } a problem?
Yes,
MustHaveHappened(Repeated.Exactly.Once)
will "pass" only when mocked method will be called with exact same parameters which you provide in the mock configuration.
A.CallTo(() => this.personRepository.DeletePersons(commonParam, new[] {personId }, false))
.MustHaveHappened(Repeated.Exactly.Once);
For commonParam
it works, because you passed same instance to the method under the test.
For new[] {personId }
it doesn't work because array given in mock configuration and instance given in the method under the test are different instances of int[]
.
You can use custom argument matching
A.CallTo(() => this.personRepository.DeletePersons(
commonParam,
A<IEnumerable<int>>.That.Matches(ids => ids.Single() == personId),
false))
.MustHaveHappened(Repeated.Exactly.Once);
Or use more convenience and readable matching for your particular case as Thomas suggested. More convenience matchers
Upvotes: 5
Reputation: 292685
Fabio is correct, but you can make it a bit simpler:
A.CallTo(() => this.personRepository.DeletePersons(
commonParam,
A<IEnumerable<int>>.That.IsSameSequenceAs(personId),
false))
.MustHaveHappened(Repeated.Exactly.Once);
Upvotes: 5
Reputation: 74
Is the new[] { ... } a problem?
Yes you are right. The new[]
creates an array with the type you use between the {...} (It's assumed by the compiler). However your method declaration uses a IEnumerable<int> ids
. So basically your test call is calling the wrong/unexisting method, due to signature mismatch.
Upvotes: 0