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);