Reputation: 1672
I'm mocking the @elastic/elasticsearch
library and I want to test that the search
method is called with the right arguments but I'm having issues accessing search
from my tests.
In my ES mock I just export an object that includes a Client
prop that returns another object that has the search
prop. This is the way search
is accessed from the library
const { Client } = require('@elastic/elasticsearch')
const client = new Client(...)
client.search(...)
__mocks__/@elastic/elasticsearch
module.exports = {
Client: jest.fn().mockImplementation(() => {
return {
search: (obj, cb) => {
return cb(
'',
{
statusCode: 200,
body: {
hits: {
hits: [
{
_source: esIndexes[obj.index]
}
]
}
}
}
)
}
}
})
}
__tests__/getAddresses.test.js
const { getAddresses } = require('../src/multiAddressLookup/utils/getAddresses')
const { Client } = require('@elastic/elasticsearch')
beforeEach(() => {
process.env.ES_CLUSTER_INDEX = 'foo'
process.env.ui = '*'
})
describe('multiAddressLookup', () => {
test('Should return the correct premises data with only the relevant "forecasted_outages"', async () => {
const event = {
foo: 'bar'
}
const esQueryResponse = {
"body": "\"foo\":\"bar\"",
"headers": {"Access-Control-Allow-Origin": '*'},
"statusCode": 200
}
await expect(getAddresses(event)).resolves.toEqual(esQueryResponse)
expect(Client().search).toHaveBeenCalled() // This fails with 0 calls registered
})
})
Upvotes: 2
Views: 2135
Reputation: 1672
I'm not sure of any exact documentation for this scenario but I got the idea while looking through the Jest: The 4 ways to create an ES6 Mock Class - Automatic mock portion of the Jest documentation.
First, the search
method in the ES mock, __mocks__/@elastic/elasticsearch
, needs to be converted into a jest mock function, jest.fn()
. Doing this gives us access to properties and values that jest mocks provide.
__mocks__/@elastic/elasticsearch.js converted
module.exports = {
Client: jest.fn().mockImplementation(() => {
return {
search: jest.fn((obj, cb) => {
return cb(
'',
{
statusCode: 200,
body: {
hits: {
hits: [
{
_source: esIndexes[obj.index]
}
]
}
}
}
)
})
}
})
}
Second, in our tests we need to follow the path from the Client
mock class until we find out methods. The syntax is MockClass.mock.results[0].value.mockFunction
.
Example Test
const { Client } = require('@elastic/elasticsearch') // This is located in the "__mocks__" folder in the root of your project
const { getAddresses } = require('../../src/getAddresses') // This is the file we wrote and what we are unit testing
describe('getAddresses', () => {
it('Should call the ES Search method', async () => {
const event = { ... }
const expected = { ... }
await expect(getAddresses(event)).resolves.toEqual(expected) // pass
expect(Client.mock.results[0].value.search).toHaveBeenCalled() // pass
})
})
Upvotes: 2