2017-05-09 9 views
1

최근에 우리는 Mongo 용 저장소의 일반 버전을 구현했습니다.Moq C# MongoDB FindAsync 반환 값

코드가 호출되는

public async Task<IList<T>> FindAsync<T>(FilterDefinition<T> t) where T : IMongoModel 
{ 
    var collection = _connection.GetCollection<T>(); 
    var result = await collection.FindAsync<T>(t); 
    return await result.ToListAsync(); 
} 

public async Task<IList<T>> FindAsync<T>(Expression<Func<T, bool>> filter) where T : IMongoModel 
{ 
    var collection = _connection.GetCollection<T>(); 
    var result = await collection.FindAsync(filter); 
    return await result.ToListAsync(); 
} 
저장소

private async Task<MongoDb.Advertisement.Service.Models.AdvertisementFiles.Advertisement> DealerZipCodeAndLocation(MongoDb.Advertisement.Service.Models.AdvertisementFiles.Advertisement advertisement, string searchPhone) 
{ 
    var matchingDealers = await _mongoRepository.FindAsync(Builders<Dealer>.Filter.ElemMatch(y => y.Phones, z => z.PhoneNumber == searchPhone)); 
    if (!matchingDealers.Any()) 
    { 
     return advertisement; 
    } 
    if (matchingDealers.Count > 1) 
    { 
     _logger.Warning("More than one dealer found with {PhoneNumber}", searchPhone); 
    } 
    var matchingDealer = matchingDealers.FirstOrDefault(); 
    if (matchingDealer.Geocode == null) 
    { 
     var geoCode = await _geoLocationCache.GetGeocodByZipCode(matchingDealer.Address.ZipCode); 

     if (geoCode.status != "OK") 
     { 
      return advertisement; 
     } 
     advertisement.Geocode = geoCode; 
     advertisement.ZipCode = matchingDealer.Address.ZipCode; 
     await UpdateGeocode<Dealer>(matchingDealer.Id, geoCode); 
    } 

    return advertisement; 
} 

도 시도 해 봤나 다음 서명

var matchingDealers = await _mongoRepository.FindAsync<Dealer>(x => x.Phones.Any(y => y.PhoneNumber == searchPhone)); 
var matchingDealers = await _mongoRepository.FindAsync(filter); 

FindAsync 호출을 조롱 할 때 반환하는 데 어려움이 있습니다. 문제는 서명이 일치하지 않거나 비동기 일 가능성이 높습니다.

내가 (전화 번호 대신에도 It.IsAny<string>()와) 두 버전을 모두 시도 설정

MOQ

_testFixture.MongoRepository.Setup(x => x.FindAsync(Builders<Dealer>.Filter.ElemMatch(y => y.Phones, z => z.PhoneNumber == _testFixture.GetAdvertisementWithNoZipCode().OriginalPhoneNumber))).Returns(Task.FromResult(_testFixture.GetDealerWithZipCode())); 
_testFixture.MongoRepository.Setup(x => x.FindAsync(Builders<Dealer>.Filter.ElemMatch(y => y.Phones, z => z.PhoneNumber == _testFixture.GetAdvertisementWithNoZipCode().OriginalPhoneNumber))).ReturnsAsync(_testFixture.GetDealerWithZipCode()); 

복귀가 시도 된 개체

public IList<Dealer> GetDealerWithZipCode() 
{ 
    return new List<Dealer> 
    { 
     new Dealer 
     { 
      Active = true, 
      DealerName = "City Chevrolet", 
      Phones = new List<Phone> 
      { 
       new Phone 
       { 
        PhoneNumber = "4033809999" 
       } 
      }, 
      MasterCode = "CHEV01", 
      RevisionDate = DateTime.UtcNow 
     } 
    }; 
} 

public async Task<IList<Dealer>> GetDealerWithZipCode() 
{ 
    return await Task.Run(() => new List<Dealer> 
    { 
     new Dealer 
     { 
      Active = true, 
      DealerName = "City Chevrolet", 
      Phones = new List<Phone> 
      { 
       new Phone 
       { 
        PhoneNumber = "4033809999" 
       } 
      }, 
      MasterCode = "CHEV01", 
      RevisionDate = DateTime.UtcNow 
     } 
    }); 
} 

예외

System.ArgumentNullException: Value cannot be null. 
Parameter name: source 
    at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source) 
    at Domain.Advertisement.Service.BackgroundProcessors.ZipCodeAndLocationProcessor.<DealerZipCodeAndLocation>d__5.MoveNext() in C:\Repos\Vader\AdSvc\domain\domain.advertisement.service\BackgroundProcessors\ZipCodeAndLocationProcessor.cs:line 60 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
    at Domain.Advertisement.Service.BackgroundProcessors.ZipCodeAndLocationProcessor.<ProcessVehicleAdvertisementLocation>d__4.MoveNext() in C:\Repos\Vader\AdSvc\domain\domain.advertisement.service\BackgroundProcessors\ZipCodeAndLocationProcessor.cs:line 42 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
    at Domain.Advertisement.Service.Tests.Processors.ZipCodeAndLocation.ZipCodeAndLocationProcessorFacts.<ProcessVehicleAdvertisementLocation_AdLineHasEmptyZipCodePhoneMatchesDealer_GeocodeIsAddedToAdvertisement>d__3.MoveNext() in C:\Repos\Vader\AdSvc\tests\domain.advertisement.service.tests\Processors\ZipCodeAndLocation\ZipCodeAndLocationProcessorFacts.cs:line 47 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Xunit.Sdk.TestInvoker`1.<>c__DisplayClass48_1.<<InvokeTestMethodAsync>b__1>d.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Xunit.Sdk.ExecutionTimer.<AggregateAsync>d__4.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Xunit.Sdk.ExceptionAggregator.<RunAsync>d__9.MoveNext() 

반환 할 객체가 없기 때문에 디버깅 할 때 ArgumentNullException이 발생합니다. 나는 내 설치에 문제가 있다는 것을 알고 있지만, 나는 어디에 있는지 알아 내려고 애 쓰고있다. 나는 가정 시험 방법을 감안할 때

+0

문제를 재현하는 데 사용할 수있는 [mcve]를 제공하십시오. 현재이 질문은 특정 답변을 얻을 수있는 충분한 컨텍스트를 제공하지 않습니다. – Nkosi

+0

@ Nkosi - 사과. 나는 정보 과부하의 밧줄을 배우거나 충분하지 않다. 다른 것이 필요한지 알려주십시오. 그것은 비동기 문제입니다, 난 그냥 올바른 조합을 생각 해낼 수 없습니다. –

답변

0

_testFixture.MongoRepository 
    .Setup(_ => _.FindAsync(It.IsAny<FilterDefinition<Dealer>>())) 
    .ReturnsAsync(_testFixture.GetDealerWithZipCode()); 

를 다음과 같이 당신이

Task<IList<T>> FindAsync<T>(FilterDefinition<T> t) where T : IMongoModel 

가 속한 가정 시험에 대한 기대를 단순화해야 설정에 저장소 모의 할 수 있어야한다 DealerZipCodeAndLocation입니다 저장소 인터페이스는 _testFixture.MongoRepository에서 제공되며 안전하게 테스트중인 메서드를 줄에 적용해야합니다.

if (matchingDealer.Geocode == null) { 
    //... 

예상되는대로 테스트를 수행하려면 로거 및 지리적 위치 캐시와 같은 다른 종속성도 적절하게 조롱되어야합니다.

+0

정말 고마워요. Moq이 서명을 해결하기 위해 서명이 일치하지 않는 문제였습니다. 대신 Linq 또는 빌더 . Moq 설정에서 필터를 사용하여 결과 FilterDefinition 통과해야했습니다. 완전히 새벽을 보지 못했습니다. –