Elastica icon indicating copy to clipboard operation
Elastica copied to clipboard

How to mock elasticsearch responses for unit tests

Open jakxnz opened this issue 4 years ago • 4 comments

Problem

I want to get unit test coverage for my own logic that invokes Elastica. How do I mock responses from Elastica to test specific outcomes?

One potential solution

Make a mock transport based on this package's Elastica\Transport\Guzzle transport, and take advantage of the Guzzle handler to mock responses.

MockTransport.php

<?php

namespace App\Tests;

use Elastica\Connection;
use Elastica\Transport\Guzzle;
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;

class MockTransport extends Guzzle
{

    /**
     * @var MockHandler
     */
    protected static $mockHandler;

    /**
     * @return MockHandler
     */
    public static function getMockHandler(): MockHandler
    {
        if (!static::$mockHandler) {
            static::$mockHandler = new MockHandler();
        }

        return static::$mockHandler;
    }

    /**
     * {@inheritDoc}
     */
    protected function _getGuzzleClient($baseUrl, $persistent = true)
    {
        return new Client([
            'base_uri' => $baseUrl,
            'handler' => static::getMockHandler(),
        ]);
    }
}

Then you can use the mock transport when you set up your client e.g

    $client = new \Elastica\Client(['transport' => MockTransport::class]);

    MockTransport::getMockHandler()->append(function () {
        return new \GuzzleHttp\Psr7\Response\Response(
            ... // Add your mock Elasticsearch response payload
        );
    });

    $response = $client->request(...); // Add your arguments

    // Make your assertions here...

I have an Injector in my project, so was able to use the injector to assign the MockHandler (during unit tests) to logic that instantiates an Elastica\Client. You may need your own approach to assign the mock handler during unit test execution.

jakxnz avatar Mar 23 '20 23:03 jakxnz

@jakxnz I must confess, this is not something I was thinking about before. Do you need anything from us or does the above work for you?

ruflin avatar Mar 25 '20 06:03 ruflin

@ruflin, thanks for engaging in this! This suits our needs, but I am open to more effective solutions if anyone knows them

jakxnz avatar Mar 25 '20 22:03 jakxnz

@jakxnz : is your logic being part of ES requests? Like a new query type or endpoint? If not, you could mock the ES response, instead of going down to mocking guzzle requests. (my 2 cents)

thePanz avatar Mar 30 '20 08:03 thePanz

No @thePanz , my logic uses all out-of-the-box types/endpoints. Mocking the ES response sounds like it could be quite clean, do you have an example of how you would do that?

jakxnz avatar Mar 31 '20 22:03 jakxnz