为什么我的模拟电话给我 "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 文件本身。