使用InMemoryConnection测试ElasticSearch
我正在尝试围绕我们使用ElasticSearch(在C#中使用Nest 1.4.2)添加测试,并希望使用InMemoryConnection,但我遗漏了一些东西(我假设)并且没有成功。
我已经创建了这个简单的Nunit测试用例,作为我的问题的一个简单示例
using System; using Elasticsearch.Net.Connection; using FluentAssertions; using Nest; using NUnit.Framework; namespace NestTest { public class InMemoryConnections { public class TestThing { public string Stuff { get; } public TestThing(string stuff) { Stuff = stuff; } } [Test] public void CanBeQueried() { var connectionSettings = new ConnectionSettings(new Uri("http://foo.test"), "default_index"); var c = new ElasticClient(connectionSettings, new InMemoryConnection(connectionSettings)); c.Index(new TestThing("peter rabbit")); var result = c.Search(sd => sd); result.ConnectionStatus.Success.Should().BeTrue(); } } }
查询成功但找不到我刚编入索引的文档…
如果我更新到NEST版本2.3.3和新语法
[Test] public void CanBeQueried() { var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()); settings.DefaultIndex("default"); var c = new ElasticClient(settings); c.Index(new TestThing("peter rabbit")); var result = c.Search(sd => sd); result.CallDetails.Success.Should().BeTrue(); result.Documents.Single().Stuff.Should().Be("peter rabbit"); }
它以同样的方式失败…即查询报告为成功但返回0文档
InMemoryConnection
实际上并不发送任何请求或从Elasticsearch接收任何响应 ; 与连接设置上的.SetConnectionStatusHandler()
一起使用(或NEST 2.x +中的.OnRequestCompleted()
),这是查看序列化请求forms的便捷方式。
当不使用InMemoryConnection
但仍然设置.SetConnectionStatusHandler()
或.OnRequestCompleted()
,根据NEST版本,当NEST 1.x或.DisableDirectStreaming()
也设置了.ExposeRawResponse(true)
时,它也是查看响应的便捷方式。 .DisableDirectStreaming()
分别在NEST 2.x +中设置。
NEST 1.x的一个例子
void Main() { var settings = new ConnectionSettings(new Uri("http://localhost:9200")) .ExposeRawResponse(true) .PrettyJson() .SetDefaultIndex("myIndexName") .MapDefaultTypeNames(d => d.Add(typeof(myPoco), string.Empty)) .SetConnectionStatusHandler(r => { // log out the requests if (r.Request != null) { Console.WriteLine("{0} {1} \n{2}\n", r.RequestMethod.ToUpperInvariant(), r.RequestUrl, Encoding.UTF8.GetString(r.Request)); } else { Console.WriteLine("{0} {1}\n", r.RequestMethod.ToUpperInvariant(), r.RequestUrl); } Console.WriteLine(); if (r.ResponseRaw != null) { Console.WriteLine("Status: {0}\n{1}\n\n{2}\n", r.HttpStatusCode, Encoding.UTF8.GetString(r.ResponseRaw), new String('-', 30)); } else { Console.WriteLine("Status: {0}\n\n{1}\n", r.HttpStatusCode, new String('-', 30)); } }); var client = new ElasticClient(settings, new InMemoryConnection()); int skipCount = 0; int takeSize = 100; var searchResults = client.Search(x => x .Query(q => q .Bool(b => b .Must(m => m.Match(mt1 => mt1.OnField(f1 => f1.status).Query("New"))))) .Skip(skipCount) .Take(takeSize) ); } public class myPoco { public string status { get; set;} }
产量
POST http://localhost:9200/myIndexName/_search?pretty=true { "from": 0, "size": 100, "query": { "bool": { "must": [ { "match": { "status": { "query": "New" } } } ] } } } Status: 0 { "USING NEST IN MEMORY CONNECTION" : null } ------------------------------
而对于NEST 2.x
void Main() { var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var defaultIndex = "default-index"; var connectionSettings = new ConnectionSettings(pool, new InMemoryConnection()) .DefaultIndex(defaultIndex) .PrettyJson() .DisableDirectStreaming() .OnRequestCompleted(response => { // log out the request if (response.RequestBodyInBytes != null) { Console.WriteLine( $"{response.HttpMethod} {response.Uri} \n" + $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); } else { Console.WriteLine($"{response.HttpMethod} {response.Uri}"); } Console.WriteLine(); // log out the response if (response.ResponseBodyInBytes != null) { Console.WriteLine($"Status: {response.HttpStatusCode}\n" + $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + $"{new string('-', 30)}\n"); } else { Console.WriteLine($"Status: {response.HttpStatusCode}\n" + $"{new string('-', 30)}\n"); } }); var client = new ElasticClient(connectionSettings); int skipCount = 0; int takeSize = 100; var searchResults = client.Search(x => x .Query(q => q .Bool(b => b .Must(m => m.Match(mt1 => mt1.Field(f1 => f1.status).Query("New"))))) .Skip(skipCount) .Take(takeSize) ); }
您当然可以使用您最喜欢的模拟框架从客户端模拟/存根响应,并且取决于客户端接口, IElasticClient
,如果这是您想要采用的路由,尽管断言请求的序列化forms符合您在SUT中的期望可能是足够。