LoveMeow
LoveMeow

Reputation: 4038

How to mock elastic search python?

I need to mock elasticsearch calls, but I am not sure how to mock them in my python unit tests. I saw this framework called ElasticMock. I tried using it the way indicated in the documentation and it gave me plenty of errors. It is here : https://github.com/vrcmarcos/elasticmock

My question is, is there any other way to mock elastic search calls?

This doesn't seem to have an answer either: Mock elastic search data. And this just indicates to actually do integration tests rather than unit tests, which is not what I want: Unit testing elastic search inside Django app.

Can anyone point me in the right direction? I have never mocked things with ElasticSearch.

Upvotes: 12

Views: 18615

Answers (3)

xpeiro
xpeiro

Reputation: 760

You have to mock the attr or method you need, for example:

import mock

with mock.patch("elasticsearch.Elasticsearch.search") as mocked_search, \
                mock.patch("elasticsearch.client.IndicesClient.create") as mocked_index_create:

            mocked_search.return_value = "pipopapu"
            mocked_index_create.return_value = {"acknowledged": True}

In order to know the path you need to mock, just explore the lib with your IDE. When you already know one you can easily find the others.

Upvotes: 7

Javi Carnero
Javi Carnero

Reputation: 467

After looking at the decorator source code, the trick for me was to reference Elasticsearch with the module:

import elasticsearch
...
elasticsearch.Elasticsearch(...

instead of

from elasticsearch import Elasticsearch
...
Elasticsearch(...

Upvotes: 4

doctorlove
doctorlove

Reputation: 19262

I'm going to give a very abstract answer because this applies to more than ES.

class ProductionCodeIWantToTest:
  def __init__(self):
    pass

  def do_something(data):
    es = ES() #or some database or whatever
    es.post(data) #or the right syntax

Now I can't test this. With one small change, injecting a dependency:

class ProductionCodeIWantToTest:
  def __init__(self, database):
    self.database = database

  def do_something(data):
    database.save(data) #or the right syntax

Now you can use the real db:

es = ES() #or some database or whatever
thing = ProductionCodeIWantToTest(es)

or test it

mock = #... up to you - just needs a save method so far
thing = ProductionCodeIWantToTest(mock)

Upvotes: 6

Related Questions