Canton
Canton

Reputation: 53

How to mock request-promise-native for NodeJS unit testing?

My NodeJS application uses request-promise-native.

import request from 'request-promise-native'
const https = require('https')

const myRequest = request.defaults({
  baseUrl: 'myBaseUrl',
  agent: new https.Agent({ keepAlive: true })
})

async function findResults() {
  const myResponse = await myRequest.get({
      uri: '/myUri'
  })
  return myResponse
}

I am trying to mock 'get' of the above request for unit testing. But it still makes the actual call and gets the results, not going through my mock object call.

I tried different variations, using Sinon:

import test from 'ava'
import sinon from 'sinon'
import Bluebird from 'bluebird'
import request from 'request-promise-native'
import { findResults } from '../services/results'

test.only(async t => {
  let response = JSON.stringify({
     statusCode: 504
  })

  sinon.stub(request, 'get').returns(Bluebird.resolve(response))

  const returnValue = await findResults()
  console.log('return: ', returnValue)

  t.is (1, 1)
})

Using Mockery (per the documentation https://www.npmjs.com/package/request-promise)

import mockery from 'mockery'
import { findResults } from '../services/results'

test.before(async t => {
    mockery.enable({
      warnOnReplace: false,
      warnOnUnregistered: false,
      useCleanCache: true
    })

  mockery.registerMock('request-promise-native', function () {
  // var response = fs.readFileSync(__dirname + '/data/' + filename, 'utf8');
    let response = JSON.stringify({
        statusCode: 9
    })
   return Bluebird.resolve(response.trim());
  })
})

test.after(async t => {
   mockery.disable()
   mockery.deregisterAll()
   // done()
})

test.only(async t => {
   const returnValue = await findResults()
   console.log('return: ', returnValue)

   t.is(1, 1)
})

I have also tried variations of proxyquire and sinon's fake server. But I couldn't get them to work.

Any suggestions?

Upvotes: 5

Views: 9198

Answers (2)

Rujoota Shah
Rujoota Shah

Reputation: 1341

I used proxyquire for this. Here is some pieces of code I used to mock request-promise:

const proxyquire = require('proxyquire');
before(function (done) {

        rpMock = function () {
            var response = generateFakeResponse();
            return Bluebird.resolve(response.trim());
        };

        done();
    });

    // actual test:
    it('tests my function', function () {
         let MyModule = proxyquire('./MyModule',{'request-promise':rpMock});
         let myModuleObj = new MyModule();
    }

Upvotes: 0

ElioRubens
ElioRubens

Reputation: 701

Normally if using sinon spy on an imported package, you would create the stub like so sinon.spy(request.prototype, 'get'). That does not work here, presumably because request is not defining the methods on the prototype. One way you could work around this is to make the stub on the instance (if you can call it that). Example below:

const request = require( 'request-promise-native')
const https = require('https')
const {expect} = require('chai')
require('mocha')
const sinon = require('sinon')
const Bluebird = require( 'bluebird')

const myRequest = request.defaults({
  baseUrl: 'myBaseUrl',
  agent: new https.Agent({ keepAlive: true })
})

async function findResults() {
  const myResponse = await myRequest.get({
      uri: '/myUri'
  })
  return myResponse
}



async function mainTest() {
  let response = JSON.stringify({
     statusCode: 504
  })
  sinon.stub(myRequest, 'get').callsFake((params) => Bluebird.resolve(response))
  const returnValue = await findResults()
  console.log('return: ', returnValue)
}

mainTest()

Upvotes: 2

Related Questions