使用Xunit和Moq无法为IndexDocumentsAsync设置预期
问题描述
我有一个向Azure认知搜索插入文档的方法,却难以对其进行单元测试。我的方法如下:
public async Task AddDocumentIntoIndexAsync(Document[] Documents, string IndexName) { IndexDocumentsBatch<CreClaim> batch = IndexDocumentsBatch.MergeOrUpload(Documents); try { IndexDocumentsResult result = await _searchClient.IndexDocumentsAsync(batch); } catch (Exception ex) { } }
我通过依赖注入注入类型为Azure.Search.Documents.SearchClient的_searchClient实例。在单元测试项目中,我按如下方式模拟SearchClient:
_searchClient = new Mock<SearchClient>(new Uri(endpoint),indexName, new AzureKeyCredential(key));
问题出在尝试设置IndexDocumentsAsync时:
var indexresult = SearchModelFactory.IndexDocumentsResult; _searchClient.Setup(x => x.IndexDocumentsAsync(batch, options, new CancellationToken())).Returns(indexresult);
运行时出现错误:
Invalid callback. Setup on method with 3 parameter(s) cannot invoke callback with different number of parameters (1).
我以为最后两个参数是可选的,于是尝试:
_searchClient.Setup(x => x.IndexDocumentsAsync(batch)).Returns(indexresult);
但出现编译问题,有人能帮忙解决吗?
解决方案
问题根源
SearchClient.IndexDocumentsAsync的重载方法需要严格匹配签名,你调用的版本接收IndexDocumentsBatch<T>和可选的IndexDocumentsOptions、CancellationToken,但Moq无法自动处理可选参数的省略,且异步方法必须返回Task<IndexDocumentsResult>而非直接返回结果。SearchModelFactory.IndexDocumentsResult是工厂方法,需要调用(带括号)才能生成实例,不能直接引用方法本身。
正确的测试设置步骤
生成有效返回结果
调用工厂方法创建IndexDocumentsResult实例:var indexResult = SearchModelFactory.IndexDocumentsResult();匹配正确重载并设置异步返回
使用It.IsAny<T>灵活匹配参数,同时用ReturnsAsync返回异步任务:// 匹配你实际调用的重载:仅传入batch,其余参数用默认值 _searchClient .Setup(x => x.IndexDocumentsAsync(It.IsAny<IndexDocumentsBatch<CreClaim>>(), null, default(CancellationToken))) .ReturnsAsync(indexResult);若需要宽松匹配所有参数组合:
_searchClient .Setup(x => x.IndexDocumentsAsync(It.IsAny<IndexDocumentsBatch<CreClaim>>(), It.IsAny<IndexDocumentsOptions>(), It.IsAny<CancellationToken>())) .ReturnsAsync(indexResult);验证方法调用(可选)
测试完成后可验证方法是否被正确调用:_searchClient.Verify(x => x.IndexDocumentsAsync(It.IsAny<IndexDocumentsBatch<CreClaim>>(), null, default), Times.Once);
注意事项
- 确保测试项目引用的
Azure.Search.Documents和Moq包版本与主项目兼容。 - 若
CreClaim类型有特定约束,要保证测试中传入的Document[]能正确转换为IndexDocumentsBatch<CreClaim>。
内容的提问来源于stack exchange,提问作者Tarun Bhatt
相关产品推荐
相关产品推荐

