Node.js - Mock result of a promise

11,413

Solution 1

Okay, i figured it out. The function doPostRequest was loaded using require, on the top of the file using const doPostRequest = require('./doPostRequest.js').doPostRequest;

In order to mock the data that comes back from a function that is loaded using require i had to use a node module called mock-require. There are more modules that can take care of this (proxyquire is a populair one) but i picked mock-require (i did not have a specific reason for choosing mock-require).

For anyone else that is stuck with a similar problem, try mock-require to mock the respose from files that are loaded using require.

Solution 2

You can use Promise.resolve to return a promise with any given value.

Promise.resolve(“hello world”);
Share:
11,413

Related videos on Youtube

Mitch
Author by

Mitch

Updated on June 04, 2022

Comments

  • Mitch
    Mitch almost 2 years

    I want to mock the result of a function within a node module so that i can run assertions. Considering the following node module:

    const doPostRequest = require('./doPostRequest.js').doPostRequest;
    const normalizeSucessResult = require('./normalizer.js').normalizeSucessResult;
    const normalizeErrorResult = require('./normalizer.js').normalizeErrorResult;
    
    exports.doPost = (params, postData) => {
      return doPostRequest(params, postData).then((res) => {
        const normalizedSuccessResult = normalizeSucessResult(res);
        return normalizedSuccessResult;
      }).catch((err) => {
        const normalizedErrorResult = normalizeErrorResult(err);
        return normalizedErrorResult;
      })
    }
    

    The function doPostRequest returns a promise. How can i fake the return value of this promise so that i can assert if normalizeSucessResult has been called? So for i have tried:

    const normalizeSucessResult = require('./normalizer.js');
    const doPostRequest = require('./doPostRequests.js');
    const doPost = require('./doPost.js');
    
    it('runs a happy flow scenario', async () => {
      let normalizeSucessResultStub = sinon.stub(normalizeSucessResult, 'normalizeSucessResult');
      let postData = { body: 'Lorum ipsum' };
      let params = { host: 'someUrl', port: 433, method: 'POST', path: '/' };
    
      sinon.stub(doPostRequest, 'doPostRequest').resolves("some response data"); //Fake response from doPostRequest
    
      return doPost.doPost(params, postData).then((res) => { //res should be equal to some response data
        expect(normalizeSucessResultStub).to.have.been.calledOnce;
        expect(normalizeSucessResultStub).to.have.been.with("some response data");
      });
    });
    

    The doPostRequest module looks like this:

    const https = require('https')
     module.exports.doPostRequest = function (params, postData) {
      return new Promise((resolve, reject) => {
        const req = https.request(params, (res) => {
          let body = []
          res.on('data', (chunk) => {
            body.push(chunk)
          })
          res.on('end', () => {
            try {
              body = JSON.parse(Buffer.concat(body).toString())
            } catch (e) {
              reject(e)
            }
            resolve(body)
          })
        })
        req.on('error', (err) => {
          reject(err)
        })
        if (postData) {
          req.write(JSON.stringify(postData))
        }
        req.end()
      })
    }
    
    • Estus Flask
      Estus Flask over 5 years
      Where's doPostRequest defined? Please, post all relevant code.
    • Mitch
      Mitch over 5 years
      The doPostRequest module is defined in a separate file. I have updated the code in order to show where it lives. If you have any ideas on how to solve this, please share. Im getting more confused by the minute...
    • Estus Flask
      Estus Flask over 5 years
      I'm not up to detailed answer, but you need to mock the module where doPostRequest was exported from (with Proxyquire or something similar) and do this before you import the module where it's used the first time (i.e doPost) module. You cannot do this with Sinon. You can only mock existing methods with Sinon, while doPostRequest is used as a function, not a method. Btw, Jest handles module mocking natively, you could do this easier by switching to it.
  • Mitch
    Mitch over 5 years
    Thanks for your help, i tried that in my code with sinon.stub(doPostRequest, 'doPostRequest').resolves("some response data");. Than when i call the method, res should be equal to some response data, but it is not. Can you show me how i can use it within my test so that res would be equal to some response data?