2

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?

2
  • Try sinon.stub(sqs.prototype, 'sendMessage') Commented Nov 16, 2018 at 16:10
  • @JonathanNewton Tried sinon.stub(sqs.prototype, 'sendMessage').callsFake( function() { return 'test' }). That gives me this error: Error: Trying to stub property 'sendMessage' of undefined Commented Nov 16, 2018 at 16:13

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

2 Comments

Works for me. Just had to change myModule to sqsOutputResultSender.
@dredbound fixed
1

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');
      })
    });

14 Comments

No, still gives me the same AssertionError: expected undefined to deeply equal 'test'. and info: Error AccessDenied: Access to the resource https://sqs.us-east-1.amazonaws.com/ is denied.
Could you move the call to sqs.sendMessage inside another function?
I could, but I'd still need to mock it in order to test that function wherever I move it.
I'm not sure why you can access it but here is a suggestion: Gist then your stub would look something like this ` sinon.stub(sqsOutputResultSender, 'sendMessage').callsFake( function() { return 'test' });`
Running that is still returning the same AssertionError: expected undefined to deeply equal 'test'. It's not replacing the function with the stub. I suspect that I'm just not using sinon correctly.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.