2017-10-16 46 views
2

我遇到了一些FakeItEasy的奇怪問題。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:系統。 INT32 [],hardRemove:假) 預期找到它正好一次,但發現它#0次呼叫中: 1:RepositoryContract.IPersonRepository.RequestInfo =僞造的Commons.Session.RequestInfo 2:RepositoryContract.IPersonRepository.DeletePersons( commonParam :Commons.CommonParam, IDS:System.Int32 [], hardRemove:假) 3:RepositoryContract.IPersonRepository.SaveChanges()

爲什麼測試失敗?

new[] { ... }有問題嗎?

在此先感謝

回答

4

新[] {...}是個問題嗎?

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

或使用更多的便利性和可讀性爲匹配您的特定情況下,托馬斯建議。 More convenience matchers

0

是新的[] {...}有問題嗎?

是的,你是對的。 new[]使用{...}(它由編譯器假定)之間使用的類型創建一個數組。但是,您的方法聲明使用IEnumerable<int> ids。所以基本上,由於簽名不匹配,您的測試呼叫會調用錯誤/未提供的方法。

+0

嗯,你確定嗎?我的意思是'new [] {...}'是'IEnumerable '也不是?我嘗試將調用改爲'新列表 {...}',但它仍然不起作用:-( – xeraphim

+0

它在運行時,它不在編譯時間中。將其中任何其他類型。 – dbencs

4

法比奧是正確的,但你可以把它簡單一點:

A.CallTo(() => this.personRepository.DeletePersons(
       commonParam, 
       A<IEnumerable<int>>.That.IsSameSequenceAs(personId), 
       false)) 
.MustHaveHappened(Repeated.Exactly.Once);