Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在CosmosSDK v3+;的FeedResponse中提供模拟值;?_C#_Azure Cosmosdb_Nsubstitute - Fatal编程技术网

C# 如何在CosmosSDK v3+;的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以进行测试 我尝试测试

我正在为我的应用程序编写一个数据访问层,并尝试模拟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);