TypeError: Cannot read properties of undefined (reading 'then') - axios post nodejs jest
TypeError: Cannot read properties of undefined (reading 'then') - axios post nodejs jest
我正在尝试使用 jest 为 axios post 请求编写单元测试。
这是我的实际功能 -
exports.getAccessToken = function (urlToCall, scope, basicAuthToken) {
return new Promise(function (resolve, reject) {
let axios = require("axios");
let qs = require("qs");
let data = qs.stringify({
grant_type: "client_credentials",
scope: scope,
});
let config = {
method: "post",
url: urlToCall,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "Basic " + basicAuthToken,
},
data: data,
};
axios(config)
.then(function (response) {
resolve(response.data);
})
.catch(function (error) {
console.log(
"error occurred while getting access token for the scope - ",
scope,
" and the error is - ",
error
);
});
});
};
这是我的单元测试代码-
const processUtils = require('../src/utils/process-utils')
const axios = require('axios')
jest.mock("axios")
describe("when getAccessToken API is successful", () => {
test('should return access token', async () => {
const expectedResponse = JSON.stringify({
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
"issued_token_type": "token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "consumer_profile:read:"
})
axios.post.mockResolvedValueOnce(() => Promise.resolve(expectedResponse))
// axios.post.mockImplementationOnce(() => Promise.resolve(expectedResponse));
let urlToCall = 'https://somehost.com/access_token/v1'
let scope = jest.fn
let basicAuthToken = jest.fn
const response = await processUtils.getAccessToken(urlToCall, scope, basicAuthToken)
expect(mockAxios.post).toHaveBeenCalledWith(urlToCall)
expect(response).toEqual(expectedResponse)
});
});
这是 运行 开玩笑时抛出的错误 -
TypeError: Cannot read properties of undefined (reading 'then')
> axios(config)
.then(function (response) {
resolve(response.data);
})
https://i.stack.imgur.com/NZiVp.png
我是节点和笑话的新手。有人可以指出我在这里缺少的东西吗?
问题是因为您的代码没有直接调用 axios
模块实例上的 post
函数,而是通过 config
隐式调用函数,而您的测试模拟正在寻找直接 axios.post
调用。有两种方法可以解决此问题。
- 将隐式
post
调用更改为显式调用:
发件人:
axios(config).then(function (response) {
收件人:
axios.post(config.url, config.data, { headers: config.headers }).then(function (response) {
这将使用 axios.post.mockResolvedValueOnce
调用的结果。
- 在测试套件设置中模拟 axios post 调用:
发件人:
jest.mock("axios")
到
jest.mock("axios", () => {
const expectedResponse = JSON.stringify({
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
"issued_token_type": "token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "consumer_profile:read:"
});
return () => new Promise((resolve) => resolve(expectedResponse));
})
这将通过 partial 模拟模拟隐式 post
调用,但是您将无法直接访问 post
方法,因此您将无法听到它的呼叫。
另外一个小注意,axios.post.mockResolvedValueOnce(() => Promise.resolve(expectedResponse))
会在调用then
时将一个函数传递给response
参数。我觉得你需要用什么mockedAxios.post.mockResolvedValueOnce(expectedResponse)
。此外,expectedResponse
应包含在 data
属性 中,如下所示:
const expectedResponse = JSON.stringify({
"data": {
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
"issued_token_type": "token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "consumer_profile:read:"
}
});
I'm trying to post the solution so that it helps someone.
Solution was found based on Ovidijus Parsiunas responses too.
Actual function -
exports.getAccessToken = function (urlToCall, scope, basicAuthToken) {
return new Promise(function (resolve, reject) {
let axios = require("axios");
let qs = require("qs");
let data = qs.stringify({
grant_type: "client_credentials",
scope: scope,
});
const requestHeaders = {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "Basic " + basicAuthToken,
};
// axios(config)
axios
.post(urlToCall, data, {
headers: requestHeaders,
})
.then(function (response) {
resolve(response.data);
})
.catch(function (error) {
console.log(
"error occurred while getting access token for the scope - ",
scope,
" and the error is - ",
error
);
});
});
};
My unit test case -
const processUtils = require('../src/utils/process-utils')
const axios = require('axios')
jest.mock("axios", () => ({
post: jest.fn(() => {
const expectedResponse = {
access_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
issued_token_type: "token-type:access_token",
token_type: "Bearer",
expires_in: 3600,
scope: "consumer_profile:read:",
};
// return () => new Promise((resolve) => resolve(expectedResponse));
return expectedResponse;
}),
}));
describe("when getAccessToken API is successful", () => {
it("should return access token", async () => {
const expectedResponse = {
data: {
access_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
issued_token_type: "token-type:access_token",
token_type: "Bearer",
expires_in: 3600,
scope: "consumer_profile:read:",
},
};
axios.post.mockResolvedValueOnce(expectedResponse);
let urlToCall =
"https://somehost.com/access_token/v1";
let scope = jest.fn();
let basicAuthToken = jest.fn();
const response = await processUtils.getAccessToken(
urlToCall,
scope,
basicAuthToken
);
console.log("response - ", response);
expect(response).toEqual(expectedResponse.data);
});
我正在尝试使用 jest 为 axios post 请求编写单元测试。 这是我的实际功能 -
exports.getAccessToken = function (urlToCall, scope, basicAuthToken) {
return new Promise(function (resolve, reject) {
let axios = require("axios");
let qs = require("qs");
let data = qs.stringify({
grant_type: "client_credentials",
scope: scope,
});
let config = {
method: "post",
url: urlToCall,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "Basic " + basicAuthToken,
},
data: data,
};
axios(config)
.then(function (response) {
resolve(response.data);
})
.catch(function (error) {
console.log(
"error occurred while getting access token for the scope - ",
scope,
" and the error is - ",
error
);
});
});
};
这是我的单元测试代码-
const processUtils = require('../src/utils/process-utils')
const axios = require('axios')
jest.mock("axios")
describe("when getAccessToken API is successful", () => {
test('should return access token', async () => {
const expectedResponse = JSON.stringify({
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
"issued_token_type": "token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "consumer_profile:read:"
})
axios.post.mockResolvedValueOnce(() => Promise.resolve(expectedResponse))
// axios.post.mockImplementationOnce(() => Promise.resolve(expectedResponse));
let urlToCall = 'https://somehost.com/access_token/v1'
let scope = jest.fn
let basicAuthToken = jest.fn
const response = await processUtils.getAccessToken(urlToCall, scope, basicAuthToken)
expect(mockAxios.post).toHaveBeenCalledWith(urlToCall)
expect(response).toEqual(expectedResponse)
});
});
这是 运行 开玩笑时抛出的错误 -
TypeError: Cannot read properties of undefined (reading 'then')
> axios(config)
.then(function (response) {
resolve(response.data);
})
https://i.stack.imgur.com/NZiVp.png 我是节点和笑话的新手。有人可以指出我在这里缺少的东西吗?
问题是因为您的代码没有直接调用 axios
模块实例上的 post
函数,而是通过 config
隐式调用函数,而您的测试模拟正在寻找直接 axios.post
调用。有两种方法可以解决此问题。
- 将隐式
post
调用更改为显式调用:
发件人:
axios(config).then(function (response) {
收件人:
axios.post(config.url, config.data, { headers: config.headers }).then(function (response) {
这将使用 axios.post.mockResolvedValueOnce
调用的结果。
- 在测试套件设置中模拟 axios post 调用:
发件人:
jest.mock("axios")
到
jest.mock("axios", () => {
const expectedResponse = JSON.stringify({
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
"issued_token_type": "token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "consumer_profile:read:"
});
return () => new Promise((resolve) => resolve(expectedResponse));
})
这将通过 partial 模拟模拟隐式 post
调用,但是您将无法直接访问 post
方法,因此您将无法听到它的呼叫。
另外一个小注意,axios.post.mockResolvedValueOnce(() => Promise.resolve(expectedResponse))
会在调用then
时将一个函数传递给response
参数。我觉得你需要用什么mockedAxios.post.mockResolvedValueOnce(expectedResponse)
。此外,expectedResponse
应包含在 data
属性 中,如下所示:
const expectedResponse = JSON.stringify({
"data": {
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
"issued_token_type": "token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "consumer_profile:read:"
}
});
I'm trying to post the solution so that it helps someone.
Solution was found based on Ovidijus Parsiunas responses too.
Actual function -
exports.getAccessToken = function (urlToCall, scope, basicAuthToken) {
return new Promise(function (resolve, reject) {
let axios = require("axios");
let qs = require("qs");
let data = qs.stringify({
grant_type: "client_credentials",
scope: scope,
});
const requestHeaders = {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "Basic " + basicAuthToken,
};
// axios(config)
axios
.post(urlToCall, data, {
headers: requestHeaders,
})
.then(function (response) {
resolve(response.data);
})
.catch(function (error) {
console.log(
"error occurred while getting access token for the scope - ",
scope,
" and the error is - ",
error
);
});
});
};
My unit test case -
const processUtils = require('../src/utils/process-utils')
const axios = require('axios')
jest.mock("axios", () => ({
post: jest.fn(() => {
const expectedResponse = {
access_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
issued_token_type: "token-type:access_token",
token_type: "Bearer",
expires_in: 3600,
scope: "consumer_profile:read:",
};
// return () => new Promise((resolve) => resolve(expectedResponse));
return expectedResponse;
}),
}));
describe("when getAccessToken API is successful", () => {
it("should return access token", async () => {
const expectedResponse = {
data: {
access_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
issued_token_type: "token-type:access_token",
token_type: "Bearer",
expires_in: 3600,
scope: "consumer_profile:read:",
},
};
axios.post.mockResolvedValueOnce(expectedResponse);
let urlToCall =
"https://somehost.com/access_token/v1";
let scope = jest.fn();
let basicAuthToken = jest.fn();
const response = await processUtils.getAccessToken(
urlToCall,
scope,
basicAuthToken
);
console.log("response - ", response);
expect(response).toEqual(expectedResponse.data);
});