.NET中Elasticsearch查询单元测试:Mock IElasticsearch客户端验证查询
如何Mock Elasticsearch客户端让查询作用于指定文档(NEST/Elasticsearch.Net)
直接Mock SearchAsync 返回固定响应的问题在于,无法验证你的查询逻辑是否真的能正确匹配目标文档。要让查询真正“作用”于你预设的文档集合,核心思路是捕获传入的查询条件,用它过滤预设文档,再构造符合逻辑的响应返回。以下是具体实现步骤:
1. 准备测试用的样本文档
先定义好你要用来验证查询的测试数据集:
var testDocuments = new List<MyDocument> { new MyDocument { Id = 1, Title = "Elasticsearch入门", Category = "技术" }, new MyDocument { Id = 2, Title = "NEST使用指南", Category = "技术" }, new MyDocument { Id = 3, Title = "美食制作教程", Category = "生活" } };
2. Mock IElasticClient并处理查询逻辑
以Moq框架为例,设置SearchAsync的回调方法,捕获传入的查询描述符,用它过滤预设文档后构造响应:
var mockElasticClient = new Mock<IElasticClient>(); mockElasticClient.Setup(x => x.SearchAsync<MyDocument>( It.IsAny<Func<SearchDescriptor<MyDocument>, ISearchRequest>>(), It.IsAny<CancellationToken>())) .ReturnsAsync((Func<SearchDescriptor<MyDocument>, ISearchRequest> searchFunc, CancellationToken ct) => { // 应用传入的查询逻辑到空的SearchDescriptor var descriptor = new SearchDescriptor<MyDocument>(); var searchRequest = searchFunc(descriptor); // 将预设文档转为IQueryable,用NEST的Queryable扩展执行查询过滤 var queryableDocs = testDocuments.AsQueryable(); var filteredDocs = queryableDocs.Search(searchRequest).Documents.ToList(); // 构造合法的ISearchResponse返回 var mockResponse = new Mock<ISearchResponse<MyDocument>>(); mockResponse.Setup(r => r.Documents).Returns(filteredDocs); mockResponse.Setup(r => r.Total).Returns(filteredDocs.Count); mockResponse.Setup(r => r.IsValid).Returns(true); return mockResponse.Object; });
3. 验证查询逻辑的正确性
现在你的微服务调用SearchAsync时,传入的查询会自动过滤预设文档,返回匹配结果。比如测试“搜索技术分类文档”的场景:
// 调用你的微服务搜索方法 var searchResult = await mySearchService.SearchByCategoryAsync("技术"); // 断言结果符合预期 Assert.Equal(2, searchResult.Total); Assert.All(searchResult.Documents, doc => Assert.Equal("技术", doc.Category));
额外:验证查询结构是否符合预期
如果不需要执行实际过滤,只想验证生成的查询是否符合预期,可以直接捕获查询描述符做断言:
mockElasticClient.Verify(x => x.SearchAsync<MyDocument>( It.Is<Func<SearchDescriptor<MyDocument>, ISearchRequest>>(func => { var descriptor = func(new SearchDescriptor<MyDocument>()); // 验证查询是否是针对Category字段的匹配查询 return descriptor.Query is MatchQuery matchQuery && matchQuery.Field == "category" && matchQuery.Query == "技术"; }), It.IsAny<CancellationToken>()), Times.Once);
内容的提问来源于stack exchange,提问作者Andrei Bularca
相关产品推荐
相关产品推荐

