最近我们为Mongo实现了一个通用版本的存储库。
存储库
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调用时,我对返回有困难。问题是签名不匹配,或者更可能是异步。
Moq设置
我已尝试过两个版本(同时使用It.IsAny<string>()
代替电话号码)
_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 :(得分:0)
鉴于我所假设的测试方法是DealerZipCodeAndLocation
,您应该能够按如下方式设置存储库模拟
_testFixture.MongoRepository
.Setup(_ => _.FindAsync(It.IsAny<FilterDefinition<Dealer>>()))
.ReturnsAsync(_testFixture.GetDealerWithZipCode());
这应该简化对测试的期望
Task<IList<T>> FindAsync<T>(FilterDefinition<T> t) where T : IMongoModel
属于_testFixture.MongoRepository
提供的存储库接口,应该可以安全地将测试中的方法运用到行
if (matchingDealer.Geocode == null) {
//...
您还需要确保正确模拟其他依赖项(如记录器和地理位置缓存),以便按预期执行测试。