FakeItEasy 没有找到电话,尽管它在那里
FakeItEasy not finding call although its there
我在使用 FakeItEasy 时遇到了一些奇怪的问题。
设想以下单元测试方法:
[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);
}
testee.DeletePerson
-方法如下所示:
public ResultatModel DeletePerson(CommonParam commonParam, int personId )
{
this.personRepository.DeletePersons(commonParam, new[] { personId });
this.personRepository.SaveChanges();
}
还有personRepository.DeletePersons
(不过这个是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;
});
}
}
这就是测试失败的原因
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()
为什么测试失败?
new[] { ... }
有问题吗?
提前致谢
Is the new[] { ... } a problem?
是的,你是对的。 new[]
使用您在 {...} 之间使用的类型创建一个数组(由编译器假定)。但是,您的方法声明使用 IEnumerable<int> ids
。所以基本上你的测试调用是调用 wrong/unexisting 方法,由于签名不匹配。
Is the new[] { ... } a problem?
是的,
MustHaveHappened(Repeated.Exactly.Once)
将 "pass" 仅当将使用您在模拟配置中提供的完全相同的参数调用模拟方法时。
A.CallTo(() => this.personRepository.DeletePersons(commonParam, new[] {personId }, false))
.MustHaveHappened(Repeated.Exactly.Once);
对于 commonParam
它有效,因为您将相同的实例传递给了测试中的方法。
对于new[] {personId }
它不起作用,因为模拟配置中给出的数组和被测方法中给出的实例是int[]
.
的不同实例
您可以使用自定义参数匹配
A.CallTo(() => this.personRepository.DeletePersons(
commonParam,
A<IEnumerable<int>>.That.Matches(ids => ids.Single() == personId),
false))
.MustHaveHappened(Repeated.Exactly.Once);
或者按照 Thomas 的建议,针对您的特定情况使用更方便和可读的匹配。 More convenience matchers
Fabio 是正确的,但您可以使其更简单一些:
A.CallTo(() => this.personRepository.DeletePersons(
commonParam,
A<IEnumerable<int>>.That.IsSameSequenceAs(personId),
false))
.MustHaveHappened(Repeated.Exactly.Once);
我在使用 FakeItEasy 时遇到了一些奇怪的问题。
设想以下单元测试方法:
[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);
}
testee.DeletePerson
-方法如下所示:
public ResultatModel DeletePerson(CommonParam commonParam, int personId )
{
this.personRepository.DeletePersons(commonParam, new[] { personId });
this.personRepository.SaveChanges();
}
还有personRepository.DeletePersons
(不过这个是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;
});
}
}
这就是测试失败的原因
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()
为什么测试失败?
new[] { ... }
有问题吗?
提前致谢
Is the new[] { ... } a problem?
是的,你是对的。 new[]
使用您在 {...} 之间使用的类型创建一个数组(由编译器假定)。但是,您的方法声明使用 IEnumerable<int> ids
。所以基本上你的测试调用是调用 wrong/unexisting 方法,由于签名不匹配。
Is the new[] { ... } a problem?
是的,
MustHaveHappened(Repeated.Exactly.Once)
将 "pass" 仅当将使用您在模拟配置中提供的完全相同的参数调用模拟方法时。
A.CallTo(() => this.personRepository.DeletePersons(commonParam, new[] {personId }, false))
.MustHaveHappened(Repeated.Exactly.Once);
对于 commonParam
它有效,因为您将相同的实例传递给了测试中的方法。
对于new[] {personId }
它不起作用,因为模拟配置中给出的数组和被测方法中给出的实例是int[]
.
您可以使用自定义参数匹配
A.CallTo(() => this.personRepository.DeletePersons(
commonParam,
A<IEnumerable<int>>.That.Matches(ids => ids.Single() == personId),
false))
.MustHaveHappened(Repeated.Exactly.Once);
或者按照 Thomas 的建议,针对您的特定情况使用更方便和可读的匹配。 More convenience matchers
Fabio 是正确的,但您可以使其更简单一些:
A.CallTo(() => this.personRepository.DeletePersons(
commonParam,
A<IEnumerable<int>>.That.IsSameSequenceAs(personId),
false))
.MustHaveHappened(Repeated.Exactly.Once);