Node.js测试时出现TypeError: axios is not a function错误求助
解决TypeError: axios is not a function问题
问题背景
在Node.js中使用axios发送POST请求,运行测试时持续抛出TypeError: axios is not a function,错误指向requestToken函数中的const axios = require('axios');语句。
原service.js代码
const axios = require('axios'); const qs = require('qs'); const requestToken = async (apiURL, reqBody) => { const postBody = qs.stringify({ client_id: reqBody.client_id, client_secret: reqBody.client_secret, grant_type: reqBody.grant_type, 'content-type': reqBody.content_type, }); const postHeaders = { 'Content-Type': 'application/json', 'Content-Length': JSON.stringify(postBody).length, Host: new URL(apiURL).hostname, Connection: 'keep-alive', }; const config = { method: 'POST', url: apiURL, headers: postHeaders, data: postBody, }; const response = await axios(config); // 错误指向此处 return response; };
原service.test.js代码
const qs = require('qs'); const axios = require('axios'); const {requestToken } = require('../../libs/service'); const apiConfig = { TOKEN_REQ_BODY: { client_id: 'client_id', client_secret: 'client_secret', grant_type: 'grant_type', content_type: 'content_type', }, AUTH_BASE_URL: 'uri', TOKEN_HEADER: { appkey: 'appkey', }, API_BASE_URL: 'API_BASE_URL', }; const tokenAxiosCalledWith = { method: 'POST', url: apiConfig.AUTH_BASE_URL, headers: apiConfig.TOKEN_HEADER, data: qs.stringify({ client_id: apiConfig.TOKEN_REQ_BODY.client_id, client_secret: apiConfig.TOKEN_REQ_BODY.client_secret, grant_type: apiConfig.TOKEN_REQ_BODY.grant_type, 'content-type': apiConfig.TOKEN_REQ_BODY.content_type, }), }; const accessToken = { data: { access_token: 'access_token', }, }; const eventData = { metadata: { method: 'POST', uri: 'uri', }, uriparams: 'uriparams', payload: tokenAxiosCalledWith.data, }; const requestHeaders = { Authorization: accessToken.data.access_token, appkey: apiConfig.TOKEN_HEADER.appkey, 'content-type': 'application/json', }; const reqBody = { method: eventData.metadata.method, baseURL: apiConfig.API_BASE_URL, url: eventData.metadata.uri, responseType: 'json', headers: requestHeaders, params: eventData.uriparams, data: eventData.payload, }; jest.mock('axios', () => jest.fn(() => accessToken)); describe('API service', () => { it('is called with requestToken', (done) => { /* eslint-disable no-unused-vars */ requestToken('https://token', reqBody).then((response) => { expect(axios).toHaveBeenCalledTimes(1); done();}) .catch((e) => { done(e); }); }); }
错误原因
- axios版本兼容问题:axios v1.0.0+对CommonJS模块导出方式做了变更,直接
require('axios')得到的是包含default属性的模块对象,而非可直接调用的axios函数。 - 测试mock不匹配:原测试中mock的axios结构与实际导出结构不符,导致service.js中获取的axios不是可调用函数。
- reqBody结构错误:测试中传入的reqBody是axios请求配置,而非
requestToken函数所需的包含client_id等字段的参数对象。 - 请求头与请求体不匹配:service.js中设置
Content-Type: application/json,但请求体是qs.stringify生成的form-urlencoded格式,会导致请求解析失败。
修复步骤
1. 修正service.js中的axios导入
将const axios = require('axios');改为const axios = require('axios').default;,获取正确的axios函数。同时修正请求头格式,并添加函数导出。
修改后的service.js:
const axios = require('axios').default; const qs = require('qs'); const requestToken = async (apiURL, reqBody) => { const postBody = qs.stringify({ client_id: reqBody.client_id, client_secret: reqBody.client_secret, grant_type: reqBody.grant_type, 'content-type': reqBody.content_type, }); // 修正Content-Type为form-urlencoded,匹配qs.stringify生成的请求体 const postHeaders = { 'Content-Type': 'application/x-www-form-urlencoded', Host: new URL(apiURL).hostname, Connection: 'keep-alive', }; const config = { method: 'POST', url: apiURL, headers: postHeaders, data: postBody, }; const response = await axios(config); return response; }; // 导出函数供测试调用 module.exports = { requestToken };
2. 修正测试文件的mock与参数
- 调整jest.mock结构,模拟axios的默认导出;
- 修改reqBody为
requestToken所需的参数结构; - 使用async/await替代done回调,简化测试代码。
修改后的service.test.js:
const qs = require('qs'); const axios = require('axios').default; const { requestToken } = require('../../libs/service'); const apiConfig = { TOKEN_REQ_BODY: { client_id: 'client_id', client_secret: 'client_secret', grant_type: 'grant_type', content_type: 'content_type', }, AUTH_BASE_URL: 'uri', TOKEN_HEADER: { appkey: 'appkey', }, API_BASE_URL: 'API_BASE_URL', }; const accessToken = { data: { access_token: 'access_token', }, }; // 修正reqBody结构,匹配requestToken所需参数 const reqBody = { client_id: apiConfig.TOKEN_REQ_BODY.client_id, client_secret: apiConfig.TOKEN_REQ_BODY.client_secret, grant_type: apiConfig.TOKEN_REQ_BODY.grant_type, content_type: apiConfig.TOKEN_REQ_BODY.content_type, }; // 模拟axios的默认导出结构 jest.mock('axios', () => ({ default: jest.fn(() => Promise.resolve(accessToken)) })); describe('API service', () => { it('is called with requestToken', async () => { await requestToken('https://token', reqBody); expect(axios).toHaveBeenCalledTimes(1); }); });
验证
运行测试后,TypeError: axios is not a function错误将被解决,测试会正常执行并验证axios调用次数。
内容的提问来源于stack exchange,提问作者R.Almoued
相关产品推荐
相关产品推荐

