Reputation: 26046
Can anyone figure out, why I get this error?:
● Test suite failed to run
ReferenceError: Cannot access 'mockResponseData' before initialization
> 1 | const axios = require('axios');
| ^
Here is a online version. https://repl.it/@SandraSchlichti/jest-playground-2#getStatusCode.test.js
getStatusCode.test.js
const axios = require('axios');
const getStatusCode = require('./getStatusCode');
const mockResponseData = {
status: 301,
statusText: 'Moved Permanently',
headers: {
location: 'https://www.google.com/',
'content-type': 'text/html; charset=UTF-8',
date: 'Thu, 12 Nov 2020 10:09:41 GMT',
expires: 'Sat, 12 Dec 2020 10:09:41 GMT',
'cache-control': 'public, max-age=2592000',
server: 'gws',
'content-length': '220',
'x-xss-protection': '0',
'x-frame-options': 'SAMEORIGIN',
'alt-svc': 'h3-Q050=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"',
connection: 'close'
}
};
// whenever Axios is called from getStatusCode() it won't make a network
// connection, but return the following instead
jest.mock("axios", () => {
return {
get: jest.fn().mockResolvedValue({
data: mockResponseData
})
};
});
describe("test getStatusCode ", () => {
// pretend to get data from the network connection
let response;
beforeAll(async () => {
response = await getStatusCode({
url: 'https://google.com',
statusCode: 200,
timeout: 1000,
maxRedirects: 0
});
});
// compare returned data with expected
it("fetches raw response but we are only interested in the statuscode", async () => {
// ensure the mocked Axios function has been called
expect(axios.get).toHaveBeenCalled();
});
describe('return value', () => {
it('should be greater than or equal to zero', () => {
expect(response).toBeGreaterThanOrEqual(0)
})
describe('have mocked axios.get() returned data.status', () => {
it('should have returned 301', async () => {
expect(await axios.get.mock.results[0].value).toHaveProperty('data.status', 301)
})
})
})
describe('axios returning rejected promise', () => {
beforeAll(() => {
// returning transformed mock
axios.get.mockRejectedValue({
data: mockResponseData
});
});
describe('called with arguments', () => {
let response;
beforeAll(async () => {
response = await getStatusCode({
url: 'https://google.com',
statusCode: 200,
timeout: 1000,
maxRedirects: 0
});
});
it('should return -1', async () => {
expect(await response.toEqual(-1));
});
});
});
});
getStatusCode.js
const axios = require('axios');
const qs = require('qs');
module.exports = async (options) => {
options = options || {};
options.url = options.url || {};
options.statusCode = options.statusCode || 0;
options.timeout = options.timeout || 1000;
options.maxRedirects = options.maxRedirects || 0;
try {
const response = await axios.get(options.url, {
timeout: options.timeout,
maxRedirects: options.maxRedirects,
// make all http status codes a success
validateStatus: function (status) {
return true;
}
});
console.log(response);
return (response.status === options.statusCode) ? 1 : 0;
} catch (error) {
return -1;
}
};
Upvotes: 3
Views: 508
Reputation: 32148
Jest hoists all of the calls to jest.mock
on the top of the scope (it's mentioned in few places in the documentation). And even though it's also mentioned that the variables prefixed with mock
will also be hoisted apparently they go below the jest.mock calls causing this error to happen.
I can advice you to use the auto-mocking feature of jest
import axios from 'axios';
jest.mock('axios')
// and then you'll be able to mock it's return value
axios.get.mockResolvedValue({
data: mockResponseData
})
it will include the module and will generate a mock function for each of it's methods. And it's biggest benefit is whenever a library method is removed jest won't generate a mock function for it and your test will fail.
Upvotes: 3