简体   繁体   中英

How to mock a function in another function nodejs

Trying to write a unittest for the below module in /utility/sqsThing.js. However I'm having diffuculty mocking the sqs.sendMessage method. Anyone know how I should go about this. I'm using the sinon library, and mocha for running the tests.

The function that I'm trying to unittest utility/sqsThing.js :

const AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-1' });
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
const outputQueURL = 'https:awsUrl';

const SQSOutputSender = (results) => {
  const params = {
    MessageBody: JSON.stringify(results),
    QueueUrl: outputQueURL,
  };
  // Method that I want to mock
  sqs.sendMessage(params, function (err, data) {
    if (err) {
      console.log('Error');
    } else {
      console.log('Success', data.MessageId);
    }
  });
};

My attempt at mocking the sqs.sendMessage method in a unittest sqsThingTest.js :

const sqsOutputResultSender = require('../utility/sqsThing');
const AWS = require('aws-sdk');
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });

const mochaccino = require('mochaccino');

const { expect } = mochaccino;
const sinon = require('sinon');


describe('SQS thing test', function() {
    beforeEach(function () {
        sinon.stub(sqs, 'sendMessage').callsFake( function() { return 'test' });
    });

    afterEach(function () {
        sqs.sendMessage.restore();
    });

  it('sqsOutputResultSender.SQSOutputSender', function() {
    // Where the mock substitution should occur
    const a = sqsOutputResultSender.SQSOutputSender('a');
    expect(a).toEqual('test');
  })
});

Running this unittest with mocha tests/unit/sqsThingTest.js however I get: AssertionError: expected undefined to deeply equal 'test' . info: Error AccessDenied: Access to the resource https://sqs.us-east-1.amazonaws.com/ is denied. .

It looks like the mock did not replace the aws api call. Anyone know how I can mock sqs.SendMessage in my test?

Try moving the declaration of sqsOutputResultSender after you have stubbed the sendmessage function

    var sqsOutputResultSender;
    const AWS = require('aws-sdk');
    const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });

    const mochaccino = require('mochaccino');

    const { expect } = mochaccino;
    const sinon = require('sinon');


    describe('SQS thing test', function() {
        beforeEach(function () {
            sinon.stub(sqs, 'sendMessage').callsFake( function() { return 'test' });
            sqsOutputResultSender = require('../utility/sqsThing');
        });

        afterEach(function () {
            sqs.sendMessage.restore();
        });

      it('sqsOutputResultSender.SQSOutputSender', function() {
        // Where the mock substitution should occur
        const a = sqsOutputResultSender.SQSOutputSender('a');
        expect(a).toEqual('test');
      })
    });

You could use rewire js it is a library that lets you inject mocked properties into your module you want to test.

Your require statement would look something like this:

var rewire = require("rewire");
var sqsOutputResultSender = rewire('../utility/sqsThing');

Rewire will allow you to mock everything in the top-level scope of you sqsThing.js file.

Also you need to return the value of sqs.sendMessage this will remove the issue expected undefined to deeply equal 'test'

Your original file would look the same just with a return statement.

//utility/sqsThing.js
const AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-1' });
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
const outputQueURL = 'https:awsUrl';

const SQSOutputSender = (results) => {
  const params = {
    MessageBody: JSON.stringify(results),
    QueueUrl: outputQueURL,
  };
  // Method that I want to mock
  return sqs.sendMessage(params, function (err, data) {
    if (err) {
      console.log('Error');
    } else {
      console.log('Success', data.MessageId);
    }
  });
};

You would then write your unit test as follows:

//sqsThingTest.js
var rewire = require("rewire");
var sqsOutputResultSender = rewire('../utility/sqsThing');
const mochaccino = require('mochaccino');
const { expect } = mochaccino;
const sinon = require('sinon');

describe('SQS thing test', function() {
    beforeEach(function () {
        sqsOutputResultSender.__set__("sqs", {
            sendMessage: function() { return 'test' }
        });
    });

  it('sqsOutputResultSender.SQSOutputSender', function() {
    // Where the mock substitution should occur
    const a = sqsOutputResultSender.SQSOutputSender('a');
    expect(a).toEqual('test');
  })
});

This example returns an object with a property of sendMessage but this could be replaces with a spy.

Rewire Docs

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