【问题标题】:ElasticSearch NEST 5.6.1 Query for unit testElasticSearch NEST 5.6.1 查询单元测试
【发布时间】:2018-11-21 16:44:44
【问题描述】:

我为弹性搜索编写了一堆查询,我想为它们编写一个单元测试。使用这篇文章moq an elastic connection 我能够进行一般的嘲笑。但是当我试图查看从我的查询中生成的 Json 时,我无法以任何方式得到它。 我尝试关注这篇帖子elsatic query moq,但它仅与旧版本的 Nest 相关,因为 ConnectionStatusRequestInformation 方法不再适用于 ISearchResponse 对象。

我的测试如下:

[TestMethod]
 public void VerifyElasticFuncJson()
{
//Arrange
var elasticService = new Mock<IElasticService>();
var elasticClient = new Mock<IElasticClient>();
var clinet = new ElasticClient();
var searchResponse = new Mock<ISearchResponse<ElasticLog>>();
elasticService.Setup(es => es.GetConnection())
    .Returns(elasticClient.Object);

elasticClient.Setup(ec => ec.Search(It.IsAny<Func<SearchDescriptor<ElasticLog>, 
                          ISearchRequest>>())).
                          Returns(searchResponse.Object);

//Act
var service = new ElasticCusipInfoQuery(elasticService.Object);
var FindFunc = service.MatchCusip("CusipA", HostName.GSMSIMPAPPR01, 
                                        LogType.Serilog);
var con = GetConnection();
var search =  con.Search<ElasticLog>(sd => sd
             .Type(LogType.Serilog)
             .Index("logstash-*")
             .Query(q => q
             .Bool(b => b
                    .Must(FindFunc)
                    )
               )     
             );
 **HERE I want to get the JSON** and assert it look as expected**
}

还有其他方法可以实现我的要求吗?

【问题讨论】:

    标签: elasticsearch nest


    【解决方案1】:

    最好的方法是使用InMemoryConnection 来捕获请求字节并将其与预期的 JSON 进行比较。这就是 NEST 的单元测试所做的。类似的东西

    private static void Main()
    {
        var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
        var connectionSettings = new ConnectionSettings(pool, new InMemoryConnection())
            .DefaultIndex("default")
            .DisableDirectStreaming();
    
        var client = new ElasticClient(connectionSettings);
    
        // Act
        var searchResponse = client.Search<Question>(s => s
           .Query(q => (q
             .Match(m => m
                   .Field(f => f.Title)
                   .Query("Kibana")
             ) || q
             .Match(m => m
                   .Field(f => f.Title)
                   .Query("Elasticsearch")
                   .Boost(2)
             )) && +q
             .Range(t => t
                   .Field(f => f.Score)
                   .GreaterThan(0)
             )
           )
        );
    
        var actual = searchResponse.RequestJson();
    
        var expected = new 
        {
            query = new {
                @bool = new {
                    must = new object[] {
                        new {
                            @bool = new {
                                should = new object[] {
                                    new {
                                        match = new {
                                            title = new {
                                                query = "Kibana"
                                            }
                                        }
                                    },
                                    new {
                                        match = new {
                                            title = new {
                                                query = "Elasticsearch",
                                                boost = 2d
                                            }
                                        }
                                    }
                                },
                            }
                        },
                        new {
                            @bool = new {
                                filter = new [] {
                                    new {
                                        range = new {
                                            score = new {
                                                gt = 0d
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        };
    
        // Assert
        Console.WriteLine(JObject.DeepEquals(JToken.FromObject(expected), JToken.Parse(actual)));
    }
    
    public static class Extensions
    {
        public static string RequestJson(this IResponse response) =>
            Encoding.UTF8.GetString(response.ApiCall.RequestBodyInBytes);
    }
    

    我对预期的 JSON 使用了匿名类型,因为它比转义的 JSON 字符串更容易使用。

    需要注意的一点是,即使 JSON 对象中有重复的对象键(只要最后一个键/值匹配),Json.NET 的 JObject.DeepEquals(...) 也会返回 true。如果您只是序列化 NEST 搜索,则不太可能会遇到这种情况,但需要注意一些事情。

    如果您要进行许多测试来检查序列化,您需要创建ConnectionSettings 的单个实例并与所有人共享,以便您可以利用其中的内部缓存并运行您的测试比在每个测试中实例化一个新实例要快。

    【讨论】:

    • 谢谢,我想你也回答了关于 Nest 2.x 的帖子。我在RequestJson() 中没有ISearchResponse 对象的方法...我使用的是Nest 5.6。也许与此有关
    • 抱歉,我是想添加它来回答,它只是一个扩展方法:) 现在添加它
    • 别担心,乐于助人:)
    • 一个后续问题。如果我想查询一个嵌套的字段,我该怎么做呢?例如filled.Host 我无法使用我的 json 定义的属性,也不能在名称中添加一个点
    • 最好为此提出一个单独的问题。带点的字段名称可以用 Dictionary 或 JObject 处理。查看嵌套查询文档:elastic.co/guide/en/elasticsearch/client/net-api/current/…
    猜你喜欢
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多