1

使用我的 lambda/node 代码运行 Jest 测试时遇到问题。当我运行 index.js 时,Axios 可以正常工作。

这是我的 index.js

const sslRootCAs = require('ssl-root-cas/latest')
const util = require('util')

exports.handler = async function (event) {  
    const axios = require('axios');
    //const user = process.env.user;
    //const pw = process.env.pw;    
    const user = '';
    const pw = '';
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
    return axios.get('https://url', {
        auth: {username: user, password: pw}, rejectUnauthorized: false
    })
        .then(res => {
            return {
                statusCode: 200,
                body: res.data
            };
        })
        .catch(err => {
            return {
                statusCode: 500,
                body: JSON.stringify(err)
            };
        });
}

这是我的 index.test.js

const lambda = require("./index");
const axios = require("axios");
const mockAdapter = require("axios-mock-adapter");

// afterEach(() => {
//   mockAxios.reset();
// });

    it("test get - this will pass", async () => {
      let mock = new mockAdapter(axios, {delayResponse: 1000});
      mock.onGet().reply({
        status: 200,
        data: {
          expand: 'schema,names',
          startAt: 0,
          maxResults: 50,
          total: 2
        }
      });
      process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
      var event = {Key: "12345"};
      const result = await lambda.handler(event);
      console.log(result);
      expect(result).toMatchObject({ status: 200, body: "test" });
      mock.reset();
    });

我用 index.test.js 尝试了多种方法。我什至去掉了所有的嘲笑,并正在测试 get 是否可行。它不是。当我运行 npm test 时,我得到“无法验证第一个证书”。

当我执行节点 index.js 时,代码不会引发该错误。我怀疑 jest 有某种类型的内置处理程序来处理该错误,或​​者可能是 Axios?

任何想法都会很棒。

谢谢,蒂姆

4

1 回答 1

2

我会先搬家

    const axios = require('axios');

超出你的函数调用。当您运行测试时,我怀疑正在发生的事情是:

  1. 您导入您的 axios 适配器。
  2. 你用 MockAdapter 模拟它
  3. 你调用你的 lambda 处理程序。
  4. 您的 lambda 处理程序使用它导入的 axios 处理程序,而不是您模拟的处理程序。
  5. 请求失败,因为 jest 阻止了它。

Axios 有一个很棒的函数叫做 create(),它可以创建一个实例(参见:https ://github.com/axios/axios )。我通常为我将在我的应用程序中使用的所有端点创建一个单独的实例,然后从一个单独的文件中导出它们。这使得重用逻辑和模拟端点变得容易。例如,您可以创建一个仅包含以下代码的文件api.js

api.js

const axios = require('axios')

export default () => axios.create({baseURL: 'https://url', timeout: 5000})

然后在你的 index.js/handler

index.js

import api from './api.js' // or const api = require('./api.js')
...
exports.handler = async function (event) {
.... 
return api.get('/', { // make sure not to repeat the baseURL
    auth: {username: user, password: pw}, rejectUnauthorized: false
})

此外,如果您使用异步等待,您可以删除您的 .then 和 .catch。这是处理 Promise 的两种不同方法。最好选择一个并坚持下去。

这样更干净,更容易阅读。

然后,在你调用 lambda 的任何函数中——比如你的测试——你可以做类似的事情:

  const result = await lambda.handler(event);
  expect(result).toMatchObject({ status: 200, body: "test" });

至于代码中的其他地方,您可以通过将所有内容包装在 try/catch 中来处理在调用函数中设置响应代码,如下所示:

try {
  const result = await lambda.handler(event);
  res.json(result.body);
catch (e) {
  res.status(500).send({error: e})
 }

测试.js

然后,您应该通过执行以下操作将模拟适配器附加到您创建的 axios 实例:

const lambda = require("./index");
const api = require("./api");
const mockAdapter = require("axios-mock-adapter");

it("test get - this will pass", async () => {
  let mock = new mockAdapter(api, {delayResponse: 1000});
  mock.onGet('/').reply({ // make sure to specify the route your're mocking
    status: 200,
    data: {
      expand: 'schema,names',
      startAt: 0,
      maxResults: 50,
      total: 2
    }
  });
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
  var event = {Key: "12345"};
  const result = await lambda.handler(event);
  console.log(result);
  expect(result).toMatchObject({ status: 200, body: "test" });
  mock.reset();
});
于 2020-08-17T22:23:04.927 回答