我在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;
            });
        }
    }


这就是测试失败的原因


  测试方法DataService.Test.PersonServiceTest.DeletePerson_WhenCalled_ThenPersonIsDeleted引发异常:
  FakeItEasy.ExpectationException:
  
  断言以下调用失败:
      RepositoryContract.IPersonRepository.DeletePersons(commonParam:Commons.CommonParam,ids:System.Int32 [],hardRemove:False)
    预期只找到一次,但在调用中找到#0次:
      1:RepositoryContract.IPersonRepository.RequestInfo =伪造的Commons.Session.RequestInfo
      2:RepositoryContract.IPersonRepository.DeletePersons(
            commonParam:Commons.CommonParam,
            id:System.Int32 [],
            hardRemove:错误)
      3:RepositoryContract.IPersonRepository.SaveChanges()


为什么测试失败?

new[] { ... }有问题吗?

提前致谢

最佳答案

new [] {...}是否有问题?


是,
仅当使用与您在模拟配置中提供的参数完全相同的模拟方法调用模拟方法时,MustHaveHappened(Repeated.Exactly.Once)才会“通过”。

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

10-07 14:22