ElasticSearch NEST 5.6.1 单元测试查询
ElasticSearch NEST 5.6.1 Query for unit test
我写了一堆查询到弹性搜索,我想为他们写一个单元测试。使用这个 post 我能够进行一般的模拟。但是当我试图查看从我的查询生成的 Json 时,我没有设法以任何方式获得它。
我试图遵循此 post ,但它仅与旧版本的 Nest 相关,因为方法 ConnectionStatus
和 RequestInformation
不再适用于 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**
}
还有其他方法可以实现我的要求吗?
执行此操作的最佳方法是使用 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.NET 的 JObject.DeepEquals(...)
将 return true
即使 JSON 对象中有重复的对象键(只要最后 key/value 匹配)。如果您只是序列化 NEST 搜索,您不太可能会遇到这种情况,但需要注意一些事情。
如果您要进行许多检查序列化的测试,您需要创建 ConnectionSettings
的单个实例并与所有人共享,这样您就可以利用其中的内部缓存,并且您的测试 运行 比在每个测试中实例化一个新实例要快。
我写了一堆查询到弹性搜索,我想为他们写一个单元测试。使用这个 post ConnectionStatus
和 RequestInformation
不再适用于 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**
}
还有其他方法可以实现我的要求吗?
执行此操作的最佳方法是使用 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.NET 的 JObject.DeepEquals(...)
将 return true
即使 JSON 对象中有重复的对象键(只要最后 key/value 匹配)。如果您只是序列化 NEST 搜索,您不太可能会遇到这种情况,但需要注意一些事情。
如果您要进行许多检查序列化的测试,您需要创建 ConnectionSettings
的单个实例并与所有人共享,这样您就可以利用其中的内部缓存,并且您的测试 运行 比在每个测试中实例化一个新实例要快。