# Mocking SearchResponse in New .NET client

**URL:** <https://discuss.elastic.co/t/mocking-searchresponse-in-new-net-client/371925>\
**Category:** Elasticsearch\
**Tags:** language-clients\
**Created:** [December 12, 2024, 4:29pm UTC](https://discuss.elastic.co/t/mocking-searchresponse-in-new-net-client/371925 "2024-12-12T16:29:19Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![imhoffdavid](https://avatars.discourse-cdn.com/v4/letter/i/35a633/32.png) [@imhoffdavid](https://discuss.elastic.co/u/imhoffdavid)\
**Post date:** [December 12, 2024, 4:29pm UTC](https://discuss.elastic.co/t/mocking-searchresponse-in-new-net-client/371925/1 "2024-12-12T16:29:19Z")

</div>

Hello, I'm relatively new to .NET ecosystem and I'm trying to write some unit tests for the new elasticsearch .NET client (v 8.16.3) and I'm running into some issues.

It seems in the past, (NEST client) you were able to mock the ISearchResponse interface and that would give you an easy mock to handle. However I don't see that interface anymore in the new client.

So after a ton of searching I found TestableResponseFactory which creates a real SearchResponse instead of a mock, and seems to be the new tool meant to accomplish testing. Which seems to work well except I'm still getting NullPointerException when trying to access my searchResponse.Documents in the code I'm testing.

```auto
var temp = new SearchResponse<GlobalWorkstationWorkflowInfo>();
_searchResponse = TestableResponseFactory.CreateSuccessfulResponse(temp, 200);

//returns _searchResponse correctly, but throws NPE when trying to access _searchResponse.Documents :(
_elasticSearchClientMock.Setup(x => x.SearchAsync<GlobalWorkstationWorkflowInfo>(It.IsAny<SearchRequestDescriptor<GlobalWorkstationWorkflowInfo>>(), default)).ReturnsAsync(_searchResponse);

```

I don't see an easy way to setup Documents using the new TestableResponseFactory, so I feel stuck now and I don't know where to go.

Could you please provide any more examples on how to test using the new .NET client? Specifically on how to handle documents?

---

<div class="post-metadata">

**Author:** ![flobernd](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/flobernd/32/124877_2.png) [@flobernd](https://discuss.elastic.co/u/flobernd)\
**Post date:** [December 13, 2024, 8:53am UTC](https://discuss.elastic.co/t/mocking-searchresponse-in-new-net-client/371925/2 "2024-12-13T08:53:51Z")

</div>

Hi @imhoffdavid,

Just a few words related to this style of testing in general:

IMO you are mocking on the wrong abtraction level. Currently, you are trying to mimic the Elasticsearch client/server behavior - which in the end does not really verify anything meaningful.

Do you have some kind of repository pattern in your application? If yes, then this would be the place where I could imagine using mocks; otherwise, you probably want an integration test instead.

As for the concrete problem:

`Documents` is not a true property of the response, but is a manually added convenience property (computed property).

You need to stub out the actual response, providing the hits:

```csharp
var temp = new SearchResponse<GlobalWorkstationWorkflowInfo>()
{
	HitsMetadata = new()
	{
		Hits = [new Hit<GlobalWorkstationWorkflowInfo>() { Source = new GlobalWorkstationWorkflowInfo() }]
	}
};

var searchResponse = TestableResponseFactory.CreateSuccessfulResponse(temp, 200);
var docs = searchResponse.Documents;

```

---

<div class="post-metadata">

**Author:** ![imhoffdavid](https://avatars.discourse-cdn.com/v4/letter/i/35a633/32.png) [@imhoffdavid](https://discuss.elastic.co/u/imhoffdavid)\
**Post date:** [December 13, 2024, 4:38pm UTC](https://discuss.elastic.co/t/mocking-searchresponse-in-new-net-client/371925/3 "2024-12-13T16:38:19Z")

</div>

@flobernd thanks for the fast reply!

Right now I'm using the client directly in my service logic, but I see how it could be nice to wrap it with a "repository" class and then just mock that. I think that is the approach I will use since it removes all the elastic logic out of my service.

However, the solution you provided to mock the response worked!

To me it still seems to me that being able to mock SearchResponse would be easier and it seems strange that ISearchResponse was removed.

---

<div class="post-metadata">

**Author:** ![bsehra](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/bsehra/32/136142_2.png) [@bsehra](https://discuss.elastic.co/u/bsehra)\
**Post date:** [January 10, 2025, 1:49pm UTC](https://discuss.elastic.co/t/mocking-searchresponse-in-new-net-client/371925/4 "2025-01-10T13:49:23Z")

</div>

@flobernd - Not sure if I understand your example above correctly, Hits is Readonly collection, how are we instantiating it?

---

<div class="post-metadata">

**Author:** ![flobernd](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/flobernd/32/124877_2.png) [@flobernd](https://discuss.elastic.co/u/flobernd)\
**Post date:** [January 10, 2025, 2:07pm UTC](https://discuss.elastic.co/t/mocking-searchresponse-in-new-net-client/371925/5 "2025-01-10T14:07:35Z")

</div>

Hi @bsehra , not sure if I understood your question correctly 😅

Why do you think it can't be initialized? The type of `Hits` is `IReadOnlyCollection<Hit<T>>`, but nothing prevents us from assigning `Hit<T>[]`, `List<Hit<T>>`, etc. to the property.

---

<div class="post-metadata">

**Author:** ![bsehra](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/bsehra/32/136142_2.png) [@bsehra](https://discuss.elastic.co/u/bsehra)\
**Post date:** [January 10, 2025, 2:37pm UTC](https://discuss.elastic.co/t/mocking-searchresponse-in-new-net-client/371925/6 "2025-01-10T14:37:46Z")

</div>

@flobernd - 😅  
Perhaps missed the context in your example 😅

I return mocked response something like this with moq:  
usage:

```auto
            elasticsearchClientMock.Setup(x => x.SearchAsync<DateDiscoveredResponseModel>(It.IsAny<Elastic.Clients.Elasticsearch.SearchRequest>(), It.IsAny<CancellationToken>()))
                .Returns(Task.FromResult(mockedResp));

```

```auto
 return new Elastic.Clients.Elasticsearch.SearchResponse<DateDiscoveredResponseModel>
 {
     Took = 0,
     TimedOut = false,
     HitsMetadata = new Elastic.Clients.Elasticsearch.Core.Search.HitsMetadata<DateDiscoveredResponseModel>
     {
         Total = new Elastic.Clients.Elasticsearch.Core.Search.TotalHits { Value = 1, Relation = Elastic.Clients.Elasticsearch.Core.Search.TotalHitsRelation.Eq },
         Hits = new[]
         {
      new Elastic.Clients.Elasticsearch.Core.Search.Hit<DateDiscoveredResponseModel>
      {
          Id = "test bs desc|Publisher1||2.0~bin",
          Index = "northeurope-akperftst-01-rg-app-date-transform",
          Fields = new Dictionary<string, object>
          {
             { "ApplicationType", "[\"bin\"]" },
             { "AppKey", "[\"test bs desc|Publisher1||2.0\"]" },
             {"FirstEventAt", "[{\"2023-05-11T10:47:22.246Z\":1}]" }
          },
          Source = null
      }
  },
         MaxScore = 0
     },
     Shards = new Elastic.Clients.Elasticsearch.ShardStatistics
     {
         Total = 1,
         Failed = 0,
         Successful = 1
     }
 };

```
