Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ElasticSearch 2.0 Nest Unit Testing with MOQ

I'm having problems creating Unit test for the search using ElasticSearch with Nest.

Unit Test

var mockSearchResponse = new Mock<ISearchResponse<Person>>();
mockSearchResponse.Setup(x => x.Documents).Returns(_people);

var mockElasticClient = new Mock<IElasticClient>();
mockElasticClient.Setup(x => x.Search(It.IsAny<Func<SearchDescriptor<Person>, SearchRequest<Person>>>())).Returns(mockSearchResponse.Object);
var service = new PersonService(mockElasticClient.Object);
var result = service.Search(string.Empty, string.Empty);
Assert.AreEqual(2,result.Count());

Working code

results = ConnectionClient.Search<Person>(s => s.Index("person_index").Query(q => q.Term(t => t.Id, searchValue))).Documents;

The result is always null, even if I do the following

var temp = ConnectionClient.Search<Person>(s => s.Index("person_index").Query(q => q.Term(t => t.Id, searchValue)));

Any help would be appreciated.

like image 372
Jeff Byers Avatar asked Apr 08 '16 15:04

Jeff Byers


1 Answers

The signature of the Func<T1, T2> passed to It.IsAny<T>() is not correct so the setup expectation will never be matched. The signature should be

It.IsAny<Func<SearchDescriptor<Person>, ISearchRequest>>()

A full working example

void Main()
{
    var people = new List<Person>
    {
        new Person { Id = 1 },
        new Person { Id = 2 },
    };

    var mockSearchResponse = new Mock<ISearchResponse<Person>>();
    mockSearchResponse.Setup(x => x.Documents).Returns(people);

    var mockElasticClient = new Mock<IElasticClient>();
    mockElasticClient.Setup(x => x
        .Search(It.IsAny<Func<SearchDescriptor<Person>, ISearchRequest>>()))
        .Returns(mockSearchResponse.Object);

    var result = mockElasticClient.Object.Search<Person>(s => s);

    Assert.AreEqual(2, result.Documents.Count()).Dump();
}

public class Person
{
    public int Id { get; set;}
}

If you don't need to stub the client then you can simply use a real client and set the IConnection to an instance of InMemoryConnection

var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
// pass an instance of InMemoryConnection so that requests are not 
// **actually** sent
var connectionSettings = new ConnectionSettings(pool, new InMemoryConnection())
        .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}");
                }

                // 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);

This way you could also capture the requests if you needed to. You could take this a step further and create your own IConnection implementation that returns stub responses.

like image 133
Russ Cam Avatar answered Oct 18 '22 22:10

Russ Cam