I have code in which I make a call to elasticsearch indices stats. Tried mocking it following way but did not work.
esIndicesStatsStub = sinon.stub(Client.indices.prototype, 'stats').returns({
promise: () => new Error()
})
The error I get is
TypeError: Cannot read property 'prototype' of undefined
I've source code like this
const { Client } = require('@elastic/elasticsearch')
const esClient = new Client({
node:'some https url'
})
esClient.indices.stats(params, function (err, data) {
if (err) {
reject(err);
} else {
if (data) {
//do something
}
//do some other thing
}
});
How do I mock elasticsearch properly with sinon
? Because i'm not allowed to use @elastic/elasticsearch-mock
CodePudding user response:
Since ES SDK defines some APIs such as indices
via the getter
function:
Object.defineProperties(API.prototype, {
//...
indices: {
get () { return this[kIndices] === null ? (this[kIndices] = new IndicesApi(this.transport)) : this[kIndices] }
},
//...
})
see v8.5.0/src/api/index.ts#L372
We should use stub.get(getterFn)
API to replace a new getter for this stub.
For these APIs such as .bulk
, .clearScroll
which are assigned directly to API.prototype
, you can call sinon.stub(Client.prototype, 'bulk')
to stub them.
At last, since your code is defined in the module scope, the code will be executed when you import
/require
it. We should arrange our stubs first, then import
/require
the module. As you can see, I use dynamic import()
.
E.g.
index.ts
:
import { Client } from '@elastic/elasticsearch';
const esClient = new Client({ node: 'http://localhost:9200' });
esClient.indices.stats({ index: 'a' }).then(console.log);
index.test.ts
:
import sinon from 'sinon';
import { Client } from '@elastic/elasticsearch';
import { IndicesStatsResponse } from '@elastic/elasticsearch/lib/api/types';
describe('74949441', () => {
it('should pass', async () => {
const indicesStatsResponseStub: IndicesStatsResponse = {
_shards: {
failed: 0,
successful: 1,
total: 2,
},
_all: {
uuid: '1',
},
};
const indicesApiStub = {
stats: sinon.stub().resolves(indicesStatsResponseStub),
};
sinon.stub(Client.prototype, 'indices').get(() => indicesApiStub);
await import('./');
sinon.assert.calledWithExactly(indicesApiStub.stats, { index: 'a' });
});
});
Test result:
74949441
{
_shards: { failed: 0, successful: 1, total: 2 },
_all: { uuid: '1' }
}
✓ should pass (609ms)
1 passing (614ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
package versions:
"@elastic/elasticsearch": "^8.5.0",
"sinon": "^8.1.1",
"mocha": "^8.2.1",