简体   繁体   中英

Jest/Node Axios Testing Throwing Errors

Having an issue with running Jest testing with my lambda/node code. When I run the index.js the Axios get works fine.

This is my 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)
            };
        });
}

This is my 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();
    });

I've tried multiple things with the index.test.js. I've even cut out all the mocking and was testing to see if the get would work. It does not. I get "unable to verify the first certificate" when I run npm test.

The code does not throw that error when I do a node index.js. I suspect jest has some type of built in handler for that error or perhaps Axios?

Any ideas would be great.

Thanks, Tim

I would start by moving

    const axios = require('axios');

out of your function call. What I suspect is happening when you run your test is this:

  1. You import your axios adapter.
  2. You mock it out with MockAdapter
  3. You call your lambda handler.
  4. Your lambda handler uses the axios handler that it imports instead of the one you mocked.
  5. The request fails because jest blocks it.

Axios has a great function called create(), which creates an instance (see: https://github.com/axios/axios ). I typically create a separate instance for all the endpoints i'm going to use in my application, and then export these from a separate file. This makes it easy to reuse logic, and mock endpoints. For example, you could create a file api.js that just has the following code:

api.js

const axios = require('axios')

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

then in your 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
})

Also, you can just delete your.then and.catch if you're using async await. Those are two different methods of dealing with promises. It's best to pick one and stick to it.

that's way cleaner and easier to read.

Then, in whatever functions you call the lambda from - like your test - you could do something like:

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

As for other places in your code, you would handle setting the response code in the calling function by wrapping everything in a try/catch like this:

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

test.js

You should then attach the mock adapter to your created instance of axios by doing this:

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();
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM