Elasticsearch-net: Mocking IndicesNamespace?

Created on 18 Dec 2019  路  7Comments  路  Source: elastic/elasticsearch-net

How do I mock IElasticClient.Indices, in other words, the IndicesNamespace?

Can we instead have it so that IElasticClient.Indices refers to an interface (for instance IIndicesNamespace instead)?

Right now, I can't mock indices using NSubstitute:

var fakeIndicesNamespace = Substitute.For<IndicesNamespace>(); //crashes with message: System.NotSupportedException : Parent does not have a default constructor. The default constructor must be explicitly defined.

var fakeElasticClient = Substitute.For<IElasticClient>();
fakeElasticClient.Indices.Returns(fakeIndicesNamespace);

Most helpful comment

Why make it so hard? Why can't we just turn IndicesNamespace into an interface? That way, everyone can mock like they are used to in virtually every single other NuGet package out there, using their own mocking framework?

All 7 comments

Hi @ffMathy - can I ask why you are substituting the IndicesNamespace?

The reason for asking is that we have various approaches for mocking the client, some detailed in these issues;

None of those issues are related to mine.

I want to mock it for unit testing 馃檪

4076 contains some approaches on how to unit test with the client;

  1. Encapsulate client usage in your in own types which you can mock/stub
  2. Use InMemoryConnection and return a specific response for a given request. Take a look at this GitHub issue as an example
  3. Use Elastic.Xunit and projects to spin up a cluster as part of your tests. Granted that these will now be integration tests. These can be referenced from our AppVeyor package feed at https://ci.appveyor.com/nuget/elasticsearch-net-abstractions which you can reference by adding to Package Sources.

If you feel these approaches are not working for your situation, would you be able to elaborate a little more on what you are trying to acheive?

Why make it so hard? Why can't we just turn IndicesNamespace into an interface? That way, everyone can mock like they are used to in virtually every single other NuGet package out there, using their own mocking framework?

It's not just about making IndicesNamespace an interface, with a single concrete implementation, though. It also requires making the response types for API calls exposed on IndicesNamespace and other namespace clients _mockable_ in some way e.g. virtual members, or again, interfaces with a single concrete implementation for each. This (re)introduces ~280 types (one for each API) into the client, increasing the size of the client binary, and increases the complexity of the async execution paths, just to support the mocking use case.

Have you taken a look at any of the approaches put forward by @codebrain?

4076 contains some approaches on how to unit test with the client;

  1. Encapsulate client usage in your in own types which you can mock/stub
  2. Use InMemoryConnection and return a specific response for a given request. Take a look at this GitHub issue as an example
  3. Use Elastic.Xunit and projects to spin up a cluster as part of your tests. Granted that these will now be integration tests. These can be referenced from our AppVeyor package feed at https://ci.appveyor.com/nuget/elasticsearch-net-abstractions which you can reference by adding to Package Sources.

If you feel these approaches are not working for your situation, would you be able to elaborate a little more on what you are trying to acheive?

@codebrain so I've looked at the suggestions and followed the rabbit hole of linked issues and those issues linked issues and have this output:

  1. I don't know if I really want to do a straight 1-1 encapsulation of all the endpoints I'm using just for testing
  2. This doesn't work for some of my methods I'm testing that take one client, so one InMemoryConnection, and then multiple requests are made within that method with different code paths depending on different responses. It seems like I can only use InMemoryConnection for mocking one response for all requests.
  3. I cant remember at the moment why but we've looked at this and cant use, I think it's the company's tech setup, but we already have integration tests anyway.

Would you have a suggestion? Maybe I don't understand InMemoryConnection fully. Context: Migrating from NEST 6.x to NEST 7.x and currently have many UTests mocking the client. cc @russcam

Was this page helpful?
0 / 5 - 0 ratings