Javascript 如何在另一个函数节点中模拟函数

Javascript 如何在另一个函数节点中模拟函数,javascript,node.js,unit-testing,mocha.js,sinon,Javascript,Node.js,Unit Testing,Mocha.js,Sinon,正在尝试在/utility/sqsThing.js中为以下模块编写单元测试。然而,我很难模拟sqs.sendMessage方法。任何人都知道我该怎么做。我正在使用sinon库和mocha来运行测试 我正在尝试单元测试的函数实用程序/sqsThing.js: const AWS = require('aws-sdk'); AWS.config.update({ region: 'us-east-1' }); const sqs = new AWS.SQS({ apiVersion: '2012-1

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

我正在尝试单元测试的函数
实用程序/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);
    }
  });
};
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');
  })
});
我试图在unittest
sqsThingTest.js
中模拟sqs.sendMessage方法:

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);
    }
  });
};
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');
  })
});
使用
mochatests/unit/sqsThingTest.js运行此单元测试
AssertionError:预期未定义为完全等于“test”
info:Error AccessDenied:访问资源https://sqs.us-east-1.amazonaws.com/ 被拒绝。


看起来模拟并没有取代aws api调用。有人知道如何在我的测试中模拟
sqs.SendMessage
吗?

请在中断
SendMessage
函数后尝试移动
sqsoutpuresultsender
的声明

    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');
      })
    });
您可以使用它作为一个库,它允许您将模拟属性注入到要测试的模块中

您的require语句如下所示:

var rewire = require("rewire");
var sqsOutputResultSender = rewire('../utility/sqsThing');
Rewire将允许您模拟您
sqsThing.js
文件顶级范围内的所有内容

您还需要返回
sqs.sendMessage的值,这将消除
预期未定义为深度相等的“测试”的问题

您的原始文件只有一个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
  return 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
的对象,但可以用spy替换


尝试sinon.stub(sqs.prototype,'sendMessage')@JonathanNewton尝试
sinon.stub(sqs.prototype,'sendMessage').callsFake(function(){return'test'})
。这给了我这个错误:
error:尝试存根未定义的属性“sendMessage”
No,仍然会给我相同的
AssertionError:预期未定义为深度相等的“test”
。和
info:Error AccessDenied:Access to the resourcehttps://sqs.us-east-1.amazonaws.com/ 被拒绝。
能否将调用移动到另一个函数中的
sqs.sendMessage
,但是我仍然需要模拟它,以便在我移动它的任何地方测试该函数。我不确定为什么您可以访问它,但这里有一个建议:然后您的存根看起来像'sinon.stub(sqsOutputResultSender,'sendMessage').callsFake(function(){return'test'})`正在运行,但仍返回相同的
AssertionError:预期未定义为深度相等的“test”
。它不是用存根替换函数。我怀疑我只是没有正确使用sinon。对我有用。只需将
myModule
更改为
sqsOutputResultSender
@dredbound-fixed