Reputation: 25996
How can I mock axios.get()
when it is inside my own custom function?
I am completely lost at this point. Hope someone can see what I am doing wrong.
I have the below getString()
function which downloads the html from a website and returns a value > 0
if the string was found and -1
if string not found.
Since getString()
uses axios.get()
to download the html, I would like to Jest mock this call.
This article is the closest I can find to my situation, but in his case, he mocks a standalone axios.request()
, where mine axios.get()
is inside my custom getString()
.
My attempt is this:
getString.test.js
const axios = require('axios');
const getString = require('./getString');
jest.mock('./getString', () => {
return {
baseURL: 'localhost',
get: jest.fn().mockResolvedValue({
data: 'xxx If you are the website administrator xxx'
}),
}
});
packages.json
{
"name": "jest",
"version": "1.0.0",
"description": "",
"main": "getString.js",
"scripts": {
"test": "jest"
},
"keywords": [],
"author": "",
"license": "ISC"
}
I have done npm init -y && npm install --save-dev jest
, but npm run test
gives me
$ npm run test
> [email protected] test /home/mje/projects/jest
> jest
sh: jest: command not found
npm ERR! code ELIFECYCLE
npm ERR! syscall spawn
npm ERR! file sh
npm ERR! errno ENOENT
npm ERR! [email protected] test: `jest`
npm ERR! spawn ENOENT
npm ERR!
npm ERR! Failed at the [email protected] test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?
The simple PoC works from the docs.
index.js
const getString = require('./getString');
(async function(){
'use strict'
const isOk = await getString({
url: 'http://localhost',
string: 'If you are the website administrator',
timeout: 1000,
maxRedirects: 0
});
console.log(isOk);
})();
getString.js
const axios = require('axios');
const qs = require('qs');
module.exports = async (options) => {
options = options || {};
options.url = options.url || {};
options.string = options.string || null;
options.timeout = options.timeout || 1000;
options.maxRedirects = options.maxRedirects || 0;
try {
const response = await axios.get(options.url, {
timeout: options.timeout,
maxRedirects: options.maxRedirects,
validateStatus: null,
transformResponse: [function (data) {
return data.search(options.string);
}]
});
return await response.data;
} catch (error) {
return -1;
}
};
Upvotes: 1
Views: 1876
Reputation: 32158
First verify if jest
is within your dependencies, and if it's not - install it
yarn add --dev jest || npm i -D jest
and then test your implementation by mocking axios
rather than the implementation that you want to test.
And the rest of the getString
could look something like this
const axios = require('axios');
const getString = require('./getString');
jest.mock('axios')
const mockResponseData = {
hello: "world"
}
describe('getString', () => {
describe('axios returning resolved promise', () => {
beforeAll(() => {
// returning transformed mock
axios.get.mockResolvedValue({
data: mockResponseData
})
})
describe('called with arguments', () => {
let result
beforeAll(() => {
result = getString({
url: 'http://localhost',
string: 'If you are the website administrator',
timeout: 1000,
maxRedirects: 0
})
})
it('should call axios.get', async () => {
await result
expect(axios.get).toHaveBeenCalledWith(
"http://localhost",
{
"maxRedirects": 0,
"timeout": 1000,
"transformResponse": [
expect.any(Function)
],
"validateStatus": null
}
)
})
it('should return the response.data', async () => {
expect(await result).toEqual(mockResponseData)
})
})
})
describe('axios returning rejected promise', () => {
beforeAll(() => {
// returning transformed mock
axios.get.mockRejectedValue({
data: mockResponseData
})
})
describe('called with arguments', () => {
let result
beforeAll(() => {
result = getString({
url: 'http://localhost',
string: 'If you are the website administrator',
timeout: 1000,
maxRedirects: 0
})
})
it('should return -1', async () => {
expect(await result).toEqual(-1)
})
})
})
})
Edit: in order to achieve 100% coverage you'll also have to test your implementation's transformResponse
and in order to do that you can mock the implementation like this
// this is not tested
import mockResponseBody from './localMock.json';
axios.get.mockImplementation((url, { transformResponse }) =>
Promise.resolve({
data: transformResponse.reduce((acc, fn) => fn(acc), mockResponseData)
})
)
Upvotes: 2