C# 如何在CosmosSDK v3+;的FeedResponse中提供模拟值;?
我正在为我的应用程序编写一个数据访问层,并尝试模拟CosmosDB SDK依赖项进行单元测试。我将NUnit与NSubstitute一起使用,遇到了一个问题,我试图模拟Container.GetItemQueryIterator的返回值 我已经成功地提供了一个mock feedIterator作为该调用的响应,以及一个mock feedResponse作为feedIterator.ReadNextAsync的返回值,但是我不知道如何将任何类型的值注入feedResponse以进行测试 我尝试测试的代码如下所示:C# 如何在CosmosSDK v3+;的FeedResponse中提供模拟值;?,c#,azure-cosmosdb,nsubstitute,C#,Azure Cosmosdb,Nsubstitute,我正在为我的应用程序编写一个数据访问层,并尝试模拟CosmosDB SDK依赖项进行单元测试。我将NUnit与NSubstitute一起使用,遇到了一个问题,我试图模拟Container.GetItemQueryIterator的返回值 我已经成功地提供了一个mock feedIterator作为该调用的响应,以及一个mock feedResponse作为feedIterator.ReadNextAsync的返回值,但是我不知道如何将任何类型的值注入feedResponse以进行测试 我尝试测试
var feedIterator=container.GetItemQueryIterator(queryDefinition);
while(feedIterator.HasMoreResults){
result.success=true;
foreach(wait feedIterator.ReadNextAsync()中的var项){
列表。添加(项目);
}
}
我试图模拟出这样的依赖关系(简化):
this.mockFeedResponse=Substitute.For(this.mockApplicationList);
this.mockFeedIterator=替换.For();
this.mockFeedIterator.ReadNextAsync().ReturnsForAnyArgs(Task.FromResult(this.mockFeedResponse));
this.mockFeedIterator.HasMoreResults.Returns(true);
查看AzureCosmosDB SDK文档,似乎有一个用于模拟的FeedResponse构造函数,它将IEnumerable作为参数,但NSSubstitute抱怨说,当我尝试传递要使用的列表时,它无法找到此构造函数。是否有一种替代方法,我可以将一些IEnumerable作为反馈反馈?我哪里做错了?我通过更改代码访问从CosmosDB收到的FeedResponse上的资源字段来解决这个问题。在我的测试中,我能够模拟Resource的返回值并获得所需的结果。您可以模拟
ReadNextAsync
以返回只定义了GetEnumerator()
的FeedResponse
模拟。然后,您创建的列表的GetEnumerator
将传递给foreach
的底层实现
下面的示例使用Moq
,但是您应该能够在实现中执行类似的操作
var mockFeedResponse = new Mock<FeedResponse<Thing>>();
mockFeedResponse
.Setup(x => x.GetEnumerator())
.Returns(
new List<Thing>
{
new Thing(),
new Thing()
}.GetEnumerator()
);
var mockFeedResponse=new Mock();
模拟反馈响应
.Setup(x=>x.GetEnumerator())
.返回(
新名单
{
新事物(),
新事物
}.GetEnumerator()
);
我还通过模拟FeedResponse
mock上的GetEnumerator
调用来管理问题。但是,需要记住的是,如果您只设置了mockFeedIterator.HasMoreResults(true)
,那么您将进入一个无限循环
我通过使用Moq的回调
方法特性解决了这个问题。我将HasMoreResults
方法配置为返回true,然后在ReadNextAsync
方法上设置回调以重新配置HasMoreResults
以返回false。这样,它将在第一次循环时进入,根据模拟的GetEnumerator
方法填充返回集合,然后退出循环并将该集合返回到测试方法
var myItems = new List<MyItem>
{
new MyItem(),
new MyItem()
};
var feedResponseMock = new Mock<FeedResponse<MyItem>>();
feedResponseMock.Setup(x => x.GetEnumerator()).Returns(myItems.GetEnumerator());
var feedIteratorMock = new Mock<FeedIterator<MyItem>>();
feedIteratorMock.Setup(f => f.HasMoreResults).Returns(true);
feedIteratorMock
.Setup(f => f.ReadNextAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(feedResponseMock.Object)
.Callback(() => feedIteratorMock
.Setup(f => f.HasMoreResults)
.Returns(false));
var containerMock = new Mock<Container>();
containerMock
.Setup(c => c.GetItemQueryIterator<MyItem>(
It.IsAny<QueryDefinition>(),
It.IsAny<string>(),
It.IsAny<QueryRequestOptions>()))
.Returns(feedIteratorMock.Object);
var myItems=新列表
{
新建MyItem(),
新的MyItem()
};
var feedResponseMock=new Mock();
Setup(x=>x.GetEnumerator()).Returns(myItems.GetEnumerator());
var feedIteratorMock=new Mock();
Setup(f=>f.HasMoreResults)。返回(true);
feedIteratorMock
.Setup(f=>f.ReadNextAsync(It.IsAny()))
.ReturnsAsync(feedResponseMock.Object)
.Callback(()=>feedIteratorMock
.Setup(f=>f.HasMoreResults)
。报税表(假));
var containerMock=new Mock();
集装箱码头
.Setup(c=>c.GetItemQueryIterator(
It.IsAny(),
It.IsAny(),
It.IsAny())
.Returns(feedIteratorMock.Object);