elastic / elasticsearch-js-mock

Mock utility for the Elasticsearch's Node.js client
https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-testing.html
Apache License 2.0
47 stars 13 forks source link

How to create ResponseErrors in TypeScript #17

Open seantalbot-jisc opened 3 years ago

seantalbot-jisc commented 3 years ago

Hi, thanks for this excellent library.

I'm trying to mock specific ResponseErrors in TypeScript but I'm getting stuck. The ResponseError constructor takes a huge amount of arguments that I'm unable to workaround without the compiler complaining or it not working.

This is as far as I've got:

import ClientMock from "@elastic/elasticsearch-mock";
import { Client, Connection } from "@elastic/elasticsearch";
import { ResponseError } from "@elastic/elasticsearch/lib/errors";

type RootCause = {
    type: string;
    reason: string;
};

export function addResponseError(
    clientMock: ClientMock,
    method: string,
    path: string,
    statusCode: number,
    rootCauses: RootCause[]
): void {
    const connection = clientMock.getConnection();
    clientMock.add(
        {
            method,
            path,
        },
        () => {
            return new ResponseError({
                body: {
                    errors: {
                        root_cause: rootCauses,
                    },
                    status: statusCode
                },
                statusCode,
                headers: {},
                meta: {
                    name: "foo",
                    context: {},
                    aborted: false,
                    attempts: 0,
                    request: {
                        id: 1,
                        options: {},
                        params: {
                            method,
                            path,
                        },
                    },
                    connection,
                },
                warnings: [],
            });
        }
    );
}

I had previously set connection to {} as Connection but I received no response in my test, so I thought I could use the one from ClientMock.getConnection() instead. However, I get an error:

Type 'typeof Connection' is missing the following properties from type 'Connection': url, ssl, id, headers, and 13 more.ts(2740) Transport.d.ts(63, 5): The expected type comes from property 'connection' which is declared here on type '{ context: Context; name: string | symbol; request: { params: TransportRequestParams; options: TransportRequestOptions; id: any; }; connection: Connection; attempts: number; aborted: boolean; sniff?: { ...; } | undefined; }'

Any suggestions?

seantalbot-jisc commented 3 years ago

I'm using

"@elastic/elasticsearch-mock": "0.3.0",
"@elastic/elasticsearch": "7.9.1",

in case that helps.

seantalbot-jisc commented 3 years ago

In case it's helpful to others, I worked around this by manually crafting one:

const err = Object.create(ResponseError.prototype);
Object.assign(err, {
    meta: {
        body: {
            status: 500,
            error: {
                type: "whatever",
            },
        },
        500,
        headers: {},
    },
});

This means the object returns true to instanceof ResponseError in my exception handler code and works for my use case.

rokumura7 commented 2 years ago

I'm getting stuck too. I'd like to use ResponseError to write tests for unexpected requests, but there is more code to generate ResponseError, in other words, the code for testing is getting mess. I'd like to know if there is a better way to mock ResponseError.

nesjett commented 2 years ago

To me, this worked out:

      mock.add({ 
          method: 'POST', 
          path: `/my_index/_bulk`
      }, () => ( 
          new ResponseError({
              body: error,
              statusCode: 404,
              headers: {},
              meta: {} as any,
              warnings: [],
          })
      ));

Note: If you want to still return the "meta" prop, you can do the same strategy with the connection: connection: {} as any

Note2: "error" is a const defined earlier, with the desired content