Search code examples
node.jsunit-testingmockingmoxios

Mock an external endpoint in NodeJs by Moxios


I am trying to mock an external endpoint of Twilio in the unit test by Moxios library. I am also using SuperTest library to provide the exceptions of the test.

My internal endpoint which is called by Front-end is:

router.get('/twilio', async (req, res, next) => {
   const result = await validatePhoneNumber(68848239, 'SG');
   res.status(200).json(result);
});

and validatePhoneNumber is a function which calls the external endpoint by Axios which I am trying to mock and not to call the actual endpoint during the test:

const validatePhoneNumber = async (phone, code) => {
  const endpoint = `https://lookups.twilio.com/v1/PhoneNumbers/${phone}?CountryCode=${code}`;

  try {
    const { status } = await axios.get(endpoint, {
      auth: {
        'username': accountSid,
        'password': authToken
      }
    });

    console.log('twilio', phone, status);

    return {
      isValid: status === 200,
      input: phone
    };
  } catch (error) {
    const { response: { status } } = error;

    if (status === 404) {
      // The phone number does not exist or is invalid.
      return {
        input: phone,
        isValid: false
      };
    } else {
      // The service did not respond corrctly.
      return {
        input: phone,
        isValid: true,
        concerns: 'Not validated by twilio'
      };
    }
  }
};

And my the unit test code:

const assert = require('assert');
const request = require('supertest');
const app = require('../app');
const axios = require('axios');
const moxios = require('moxios');

describe('some-thing', () => {

    beforeEach(function () {
        moxios.install()
    })

    afterEach(function () {
        moxios.uninstall()
    })

    it('stub response for any matching request URL', async (done) => {

        // Match against an exact URL value
        moxios.stubRequest(/https:\/\/lookup.twilio.*/, {
            status: 200,
            responseText: { "isValid": true, "input": 68848239 }
        });

        request(app)
            .get('/twilio')
            .expect(200, { "isValid": true, "input": 68848239 }, done);
    });
});

If in my case Moxios is the right way to mock any external endpoints, I am getting the error below:

 Error: Timeout of 3000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (c:\Source\Samples\Twilio\myproject\test\twilio.test.js)

I increased the time out to 10000 but still I get a same error. Appreciate any hint or help.


Solution

  • I tried different ways but I prefer to go on with axios-mock-adapter library to mock any request through Axios.

    Example:

    const app = require('../app');
    const axios = require('axios');
    const request = require('supertest');
    const MockAdapter = require('axios-mock-adapter');
    
    
    describe('Valid phone number', () => {
        it('Should return data from response', (done) => {
    
            let mockAdapter = new MockAdapter(axios);
    
            mockAdapter.onGet(twilioEndpoint)
                .reply(200);
    
            request(app)
                .post('/api/validation')
                .set('Content-Type', 'application/json')
                .send(JSON.stringify(configuration))
                .expect(200, { "isValid": true, "input": "68848239" }, done);
        });
    });
    

    More information here