为什么我的模拟电话给我 "Cannot read property 'then' of undefined"
Why is my mock call giving me an "Cannot read property 'then' of undefined"
我很确定这与异步调用有关,但这是我的大脑所能达到的范围。
调用函数为:
const { messageNodeResponse } = require('../../../app/lib/message-node-response');
jest.mock('../../../app/lib/am-api.js');
describe('message node response', () => {
it('should check for message node prompt.', async () => {
const req = {
session:
{
payload: {
callbacks: [{
type: 'NameCallback',
output: [{ name: 'prompt', value: 'resendExpiredOTP' }],
input: [{ name: 'IDToken1', value: '' }],
},
{
type: 'NameCallback',
output: [{ name: 'prompt', value: 0 }],
input: [{ name: 'IDToken2', value: '' }],
}],
},
},
};
const res = await messageNodeResponse(req, 'registration');
expect(res.statusCode).toEqual(200);
});
});
正在测试的函数(在message-node-response.js):
const messageNodeResponse = (req, api) => {
const requestBody = req.session.payload;
requestBody.callbacks[1].input[0].value = 0;
const apiCall = assignApi(api);
return apiCall(req, requestBody)
.then((result) => {
logger.debug(result.data);
req.session.payload = result.data;
}).catch((err) => {
throw err;
});
};
module.exports = { messageNodeResponse };
运行 单元测试给我以下错误:“TypeError: Cannot read 属性 'then' of undefined”指的是行“return apiCall(req , 请求正文)".
应要求,am-api.js:
const axios = require('axios');
const { v1: uuid } = require('uuid');
const post = async (url, data, req) => axios.post(
url,
data,
{
headers: {
'Content-Type': 'application/json',
'Accept-API-Version': 'protocol=1.0,resource=2.1',
language: req.cookies.lng ? req.cookies.lng : 'en',
...(req.session.clientId) && { 'client-id': req.session.clientId },
...(req.session.id) && { 'session-id': req.session.id },
...((req.headers['correlation-id']) && { 'correlation-id': req.headers['correlation-id'] }) || { 'correlation-id': uuid() },
...(req.headers['user-agent']) && { 'User-Agent': req.headers['user-agent'] },
...(req.headers['x-forwarded-for']) && { 'X-Forwarded-For': req.headers['x-forwarded-for'] },
},
},
);
const registrationApi = async (req, data) => {
const url = `${process.env.AM_API_URL}${process.env.AM_REALM_PATH}/authenticate?service=${process.env.AM_REGISTRATION_TREE_NAME}&authIndexType=service&authIndexValue=${process.env.AM_REGISTRATION_TREE_NAME}`;
return post(url, data, req);
};
const authenticationApi = async (req, data) => {
const url = `${process.env.AM_API_URL}${process.env.AM_REALM_PATH}/authenticate?service=${process.env.AM_AUTHENTICATION_TREE_NAME}&authIndexType=service&authIndexValue=${process.env.AM_AUTHENTICATION_TREE_NAME}`;
return post(url, data, req);
};
const passwordResetApi = async (req, data) => {
const url = `${process.env.AM_API_URL}${process.env.AM_REALM_PATH}/authenticate?service=${process.env.AM_PASSWORD_RESET_TREE_NAME}&authIndexType=service&authIndexValue=${process.env.AM_PASSWORD_RESET_TREE_NAME}`;
return post(url, data, req);
};
const accountRecoveryApi = async (req, data) => {
const url = `${process.env.AM_API_URL}${process.env.AM_REALM_PATH}/authenticate?service=${process.env.AM_ACCOUNT_RECOVERY_TREE_NAME}&authIndexType=service&authIndexValue=${process.env.AM_ACCOUNT_RECOVERY_TREE_NAME}`;
return post(url, data, req);
};
module.exports = {
registrationApi,
authenticationApi,
passwordResetApi,
accountRecoveryApi,
};
当前的 jest 实现 (v27.5) 仅在 auto-mocking 时使用 the synchronous function definitions。
此外,模拟函数的默认返回值为 undefined
。
要正确定义模拟,可以使用第二个 jest.mock()
函数参数,即 module factory.
jest.mock('../../../app/lib/am-api.js', () => ({
registrationApi: () => Promise.resolve({ data: 42 }),
authenticationApi: () => Promise.resolve({ data: 42 }),
passwordResetApi: () => Promise.resolve({ data: 42 }),
accountRecoveryApi: () => Promise.resolve({ data: 42 })
}));
您的另一个选择是使用 mockAxios
module 而不模拟您的 api 文件本身。
我很确定这与异步调用有关,但这是我的大脑所能达到的范围。
调用函数为:
const { messageNodeResponse } = require('../../../app/lib/message-node-response');
jest.mock('../../../app/lib/am-api.js');
describe('message node response', () => {
it('should check for message node prompt.', async () => {
const req = {
session:
{
payload: {
callbacks: [{
type: 'NameCallback',
output: [{ name: 'prompt', value: 'resendExpiredOTP' }],
input: [{ name: 'IDToken1', value: '' }],
},
{
type: 'NameCallback',
output: [{ name: 'prompt', value: 0 }],
input: [{ name: 'IDToken2', value: '' }],
}],
},
},
};
const res = await messageNodeResponse(req, 'registration');
expect(res.statusCode).toEqual(200);
});
});
正在测试的函数(在message-node-response.js):
const messageNodeResponse = (req, api) => {
const requestBody = req.session.payload;
requestBody.callbacks[1].input[0].value = 0;
const apiCall = assignApi(api);
return apiCall(req, requestBody)
.then((result) => {
logger.debug(result.data);
req.session.payload = result.data;
}).catch((err) => {
throw err;
});
};
module.exports = { messageNodeResponse };
运行 单元测试给我以下错误:“TypeError: Cannot read 属性 'then' of undefined”指的是行“return apiCall(req , 请求正文)".
应要求,am-api.js:
const axios = require('axios');
const { v1: uuid } = require('uuid');
const post = async (url, data, req) => axios.post(
url,
data,
{
headers: {
'Content-Type': 'application/json',
'Accept-API-Version': 'protocol=1.0,resource=2.1',
language: req.cookies.lng ? req.cookies.lng : 'en',
...(req.session.clientId) && { 'client-id': req.session.clientId },
...(req.session.id) && { 'session-id': req.session.id },
...((req.headers['correlation-id']) && { 'correlation-id': req.headers['correlation-id'] }) || { 'correlation-id': uuid() },
...(req.headers['user-agent']) && { 'User-Agent': req.headers['user-agent'] },
...(req.headers['x-forwarded-for']) && { 'X-Forwarded-For': req.headers['x-forwarded-for'] },
},
},
);
const registrationApi = async (req, data) => {
const url = `${process.env.AM_API_URL}${process.env.AM_REALM_PATH}/authenticate?service=${process.env.AM_REGISTRATION_TREE_NAME}&authIndexType=service&authIndexValue=${process.env.AM_REGISTRATION_TREE_NAME}`;
return post(url, data, req);
};
const authenticationApi = async (req, data) => {
const url = `${process.env.AM_API_URL}${process.env.AM_REALM_PATH}/authenticate?service=${process.env.AM_AUTHENTICATION_TREE_NAME}&authIndexType=service&authIndexValue=${process.env.AM_AUTHENTICATION_TREE_NAME}`;
return post(url, data, req);
};
const passwordResetApi = async (req, data) => {
const url = `${process.env.AM_API_URL}${process.env.AM_REALM_PATH}/authenticate?service=${process.env.AM_PASSWORD_RESET_TREE_NAME}&authIndexType=service&authIndexValue=${process.env.AM_PASSWORD_RESET_TREE_NAME}`;
return post(url, data, req);
};
const accountRecoveryApi = async (req, data) => {
const url = `${process.env.AM_API_URL}${process.env.AM_REALM_PATH}/authenticate?service=${process.env.AM_ACCOUNT_RECOVERY_TREE_NAME}&authIndexType=service&authIndexValue=${process.env.AM_ACCOUNT_RECOVERY_TREE_NAME}`;
return post(url, data, req);
};
module.exports = {
registrationApi,
authenticationApi,
passwordResetApi,
accountRecoveryApi,
};
当前的 jest 实现 (v27.5) 仅在 auto-mocking 时使用 the synchronous function definitions。
此外,模拟函数的默认返回值为 undefined
。
要正确定义模拟,可以使用第二个 jest.mock()
函数参数,即 module factory.
jest.mock('../../../app/lib/am-api.js', () => ({
registrationApi: () => Promise.resolve({ data: 42 }),
authenticationApi: () => Promise.resolve({ data: 42 }),
passwordResetApi: () => Promise.resolve({ data: 42 }),
accountRecoveryApi: () => Promise.resolve({ data: 42 })
}));
您的另一个选择是使用 mockAxios
module 而不模拟您的 api 文件本身。