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

Canton picture Canton · Oct 9, 2017 · Viewed 8.5k times · Source

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?

Answer

ElioRubens picture ElioRubens · Oct 10, 2017

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