如何在另一个函数nodejs中模拟一个函数

时间:2018-11-16 16:07:23

标签: javascript node.js unit-testing mocha sinon

尝试在/utility/sqsThing.js中为以下模块编写单元测试。但是,我在嘲笑sqs.sendMessage方法。任何人都知道我应该怎么做。我正在使用sinon库和mocha来运行测试。

我要对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);
    }
  });
};

我尝试在单元测试sqsThingTest.js中模拟sqs.sendMessage方法:

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

使用mocha tests/unit/sqsThingTest.js运行此单元测试,但是得到: AssertionError: expected undefined to deeply equal 'test'info: Error AccessDenied: Access to the resource https://sqs.us-east-1.amazonaws.com/ is denied.

看起来该模拟并未取代aws api调用。有人知道我可以在测试中嘲笑sqs.SendMessage吗?

2 个答案:

答案 0 :(得分: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');
      })
    });

答案 1 :(得分:1)

您可以使用rewire js,它是一个库,可让您将模拟的属性注入到要测试的模块中。

您的require语句看起来像这样:

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

通过Rewire,您可以模拟sqsThing.js文件顶级范围内的所有内容。

此外,您需要返回sqs.sendMessage的值,这将消除问题expected undefined to deeply equal 'test'

仅使用return语句,您的原始文件就会看起来一样。

//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
  retun sqs.sendMessage(params, function (err, data) {
    if (err) {
      console.log('Error');
    } else {
      console.log('Success', data.MessageId);
    }
  });
};

然后您将编写单元测试,如下所示:

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

此示例返回一个对象,其属性为sendMessage,但是可以用间谍代替。

Rewire Docs