Cosmos SDK v3+中如何为FeedResponse注入模拟值(NSubstitute+NUnit)
解决NSubstitute Mock CosmosDB FeedResponse无法注入测试数据的问题
你遇到的核心问题是:FeedResponseSubstitute.For<FeedResponse<T>>(mockApplicationList)会报错找不到构造函数。
下面给你两种实用的解决方案,根据你的测试需求选择:
方案一:自定义FeedResponse子类(灵活可控)
如果需要模拟FeedResponse的其他属性(比如请求耗时、状态码等),或者希望更贴近真实的FeedResponse行为,建议自己实现一个子类:
public class TestFeedResponse<T> : FeedResponse<T> { private readonly IEnumerable<T> _items; public TestFeedResponse(IEnumerable<T> items) { _items = items; } // 重写枚举器方法,返回测试数据 public override IEnumerator<T> GetEnumerator() { return _items.GetEnumerator(); } // 可选:如果需要测试其他属性,比如RequestCharge,可以重写对应的属性 public override double RequestCharge => 1.0; public override HttpStatusCode StatusCode => HttpStatusCode.OK; }
然后在你的测试代码中直接实例化这个子类,代替Mock:
// 准备测试数据 var mockApplicationList = new List<YourEntityType> { new YourEntityType { /* 属性赋值 */ }, new YourEntityType { /* 属性赋值 */ } }; // 创建自定义的FeedResponse实例 var testFeedResponse = new TestFeedResponse<YourEntityType>(mockApplicationList); // 配置FeedIterator的行为 this.mockFeedIterator.ReadNextAsync().Returns(Task.FromResult(testFeedResponse)); // 注意:要控制HasMoreResults避免无限循环,比如第一次返回true,第二次返回false this.mockFeedIterator.HasMoreResults.Returns(true, false);
方案二:直接Mock FeedResponse的枚举行为(快速简洁)
如果只需要模拟返回的列表项,不需要关心FeedResponse的其他属性,可以直接Mock它的GetEnumerator方法:
// 准备测试数据 var mockApplicationList = new List<YourEntityType> { new YourEntityType { /* 属性赋值 */ }, new YourEntityType { /* 属性赋值 */ } }; // Mock FeedResponse var mockFeedResponse = Substitute.For<FeedResponse<YourEntityType>>(); // 让它返回测试数据的枚举器 mockFeedResponse.GetEnumerator().Returns(mockApplicationList.GetEnumerator()); // 配置FeedIterator this.mockFeedIterator.ReadNextAsync().Returns(Task.FromResult(mockFeedResponse)); // 同样要控制HasMoreResults的返回值 this.mockFeedIterator.HasMoreResults.Returns(true, false);
额外提醒
你的测试代码里的while (feedIterator.HasMoreResults)循环,如果HasMoreResults一直返回true会导致无限循环,所以一定要用Returns(true, false)这种方式,让迭代器在一次读取后就停止返回更多结果。
内容的提问来源于stack exchange,提问作者Sin
相关产品推荐
相关产品推荐

