为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 CosmosSDK v3+ 的 FeedResponse 中提供模拟值?

如何在 CosmosSDK v3+ 的 FeedResponse 中提供模拟值?

PHP
牧羊人nacy 2024-01-20 21:32:28
我正在为我的应用程序编写一个数据访问层,并尝试模拟 CosmosDB SDK 依赖项以进行单元测试。我将 NUnit 与 NSubstitute 一起使用,并遇到了尝试模拟 Container.GetItemQueryIterator 的返回值的问题。我已经成功提供了一个模拟 feedIterator 作为该调用的响应,并提供了一个模拟 feedResponse 作为 feedIterator.ReadNextAsync 的返回值,但我无法弄清楚如何将任何类型的值注入到 FeedResponse 中进行测试我试图测试的代码如下所示:var feedIterator = container.GetItemQueryIterator<T>(queryDefinition);  while (feedIterator.HasMoreResults){    result.success = true;    foreach (var item in await feedIterator.ReadNextAsync()){      list.Add(item);    }  }我尝试模拟这样的依赖关系(简化):this.mockFeedResponse = Substitute.For<FeedResponse<T>>(this.mockApplicationList);         this.mockFeedIterator = Substitute.For<FeedIterator<T>>();this.mockFeedIterator.ReadNextAsync().ReturnsForAnyArgs(Task.FromResult(this.mockFeedResponse));this.mockFeedIterator.HasMoreResults.Returns(true);查看 AzureCosmosDB SDK 文档,似乎有一个用于模拟的 FeedResponse 构造函数,它采用 IEnumerable 作为参数,但 NSubstitute 抱怨告诉我,当我尝试传入要使用的列表时,它找不到此构造函数。有没有一种替代方案可以将一些 IEnumerable 作为 FeedResponse 提供?我哪里出错了?
查看完整描述

3 回答

?
慕尼黑的夜晚无繁华

TA贡献1864条经验 获得超6个赞

GetEnumerator我还通过模拟模拟中的呼叫来解决这个问题FeedResponse。但是,需要记住的是,如果您只是设置mockFeedIterator.HasMoreResults(true),您最终会陷入无限循环。


我通过使用 Moq 的Callback方法功能解决了这个问题。我将该HasMoreResults方法配置为返回 true,然后在该ReadNextAsync方法上设置回调以重新配置HasMoreResults为返回 false。这样,它将while第一次进入循环,根据模拟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);


查看完整回答
反对 回复 2024-01-20
?
茅侃侃

TA贡献1842条经验 获得超21个赞

您可以模拟返回仅已定义的ReadNextAsync模拟。然后,您创建的 的将会传递到 的底层实现。FeedResponseGetEnumerator()GetEnumeratorListforeach


以下示例使用Moq,但您应该能够在实现中执行类似的操作。


var mockFeedResponse = new Mock<FeedResponse<Thing>>();

mockFeedResponse

    .Setup(x => x.GetEnumerator())

    .Returns(

        new List<Thing>

        {

            new Thing(),

            new Thing()

        }.GetEnumerator()

    );


查看完整回答
反对 回复 2024-01-20
?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

无论如何,我通过更改代码来访问从 CosmosDB 收到的 FeedResponse 上的 Resource 字段来解决这个问题。在我的测试中,我能够模拟 Resource 的返回值并获得所需的结果。



查看完整回答
反对 回复 2024-01-20
  • 3 回答
  • 0 关注
  • 103 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信