Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 如何模拟/传递使用mocha chai sinon执行其中函数的Nodejs helper实用程序_Node.js_Unit Testing_Mocha.js_Sinon_Chai - Fatal编程技术网

Node.js 如何模拟/传递使用mocha chai sinon执行其中函数的Nodejs helper实用程序

Node.js 如何模拟/传递使用mocha chai sinon执行其中函数的Nodejs helper实用程序,node.js,unit-testing,mocha.js,sinon,chai,Node.js,Unit Testing,Mocha.js,Sinon,Chai,假设我有一个如下所示的文件: src/blah.js var Foo = require("../../something/foo.js"); var goo = new Foo({ host: argv.host.toString(), port: parseInt(argv.port) }); goo.order("service_name"); goo.do("invalidPhone", function(req, done) { goo.talk('newFunc', '

假设我有一个如下所示的文件:

src/blah.js

var Foo = require("../../something/foo.js");

var goo = new Foo({
  host: argv.host.toString(),
  port: parseInt(argv.port)
});
goo.order("service_name");
goo.do("invalidPhone", function(req, done) {
  goo.talk('newFunc', 'newAct', req.data, function(newActErr, newActResponse){
       done(newActResponse)
  })
});

exports.goo = goo;
其中“something/foo.js”是执行各种功能的实用工具助手项目。 比如说,
goo.order
在某个地方注册了服务名称,
goo.do
实际使用
invalidPhone
作为函数名执行一些工作

在这种情况下,使用一些参数
req
invalidPhone
函数进行一些其他服务调用。调用
invalidPhone
函数时,该函数应打印“Here!”以及
req.data
中的任何内容

我是否需要为
invalidPhone
函数编写一个单元测试用例?我假设要实现这一点,我需要以某种方式模拟
goo.do()
,但我该怎么做呢

我试着编写一个测试用例,如下所示:

var eventService = require("../src/blah");
var base = eventService.goo;
var sinon = require("sinon");

describe("Goo Blah service", function(done) {
  beforeEach(function() {
    this.consoleSpy = sinon.spy(console, "log");
  });

  afterEach(function() {
    this.consoleSpy.restore();
  });

  it("Response should be logged", function() {
    goo.action("invalidPhone", "a123456789");
    this.consoleSpy.called.should.be.true;
  });
});
但上述措施似乎并不奏效

编辑1:如果我的代码如下所示,并且我有一个新函数
goo.talk
用于模拟/存根,并在
newActErr
newActResp
中返回一些值,该怎么办?值
newFunc
newAct
可以更改。那我该怎么做呢

var Foo = require("../../something/foo.js");

var goo = new Foo({
  host: argv.host.toString(),
  port: parseInt(argv.port)
});
goo.order("service_name");
goo.do("invalidPhone", function(req, done) {
  goo.talk('newFunc', 'newAct', req.data, function(newActErr, newActResponse){
       if(newActResponse.status){
          done(null, newActResponse)
       } else {
          done('error', null)
       }

  })
});

exports.goo = goo;
根据deerawan提供的答案提示/帮助,我尝试了以下方法:

talkStub = sinon.stub().withArgs('newFunc', 'newAct', {data: "name"}).returns({"status":"online"})

您的测试无法工作,因为您在加载源文件
blah
后在文件开头模拟/spy
console.log

var eventService = require("../src/blah");
除此之外,如果您可以模拟
Foo
类,使测试变得孤立,那么也会更好

我建议使用
proxyquire
来帮助完成这些工作
Proxyquire
require
类似,但也可以对源文件中的任何依赖项进行模拟

请看下面的解决方案:

const chai = require('chai');
const proxyquire = require('proxyquire');
const sinon = require('sinon');

// need to specify this so Foo constructor can be initialized
process.argv.host = 'http';
process.argv.port = '333';

describe("Goo Blah service", function() {
  let consoleSpy;
  let orderStub;
  let doStub;

  beforeEach(function() {
    orderStub = sinon.stub();
    doStub = sinon.stub().yields({ data: 'mine' });

    // this our mock for Foo class
    function MockFoo() {
      return {
        order: orderStub,
        do: doStub,
      }  
    }

    consoleSpy = sinon.spy(console, 'log');

    // require the source file and mock `foo`
    proxyquire('../src/blah', { '../../something/foo.js': MockFoo } );
  });

  afterEach(function() {
    sinon.restore();
  });

  it("Response should be logged", function() {
    sinon.assert.calledWith(orderStub, 'service_name');
    sinon.assert.calledWith(doStub, 'invalidPhone');

    sinon.assert.called(consoleSpy);
    sinon.assert.calledWith(consoleSpy, 'Here!', 'mine');
  });
});

希望对您有所帮助

谢谢您的帮助。我一定会尝试实现这一点,看看我是否能用你提供的想法解决我的问题。我有一个后续问题/疑问,如主要问题中的“编辑1”所示。你能看一看并给我一些想法吗?@user1452759你应该使用
yields
for
goo.talk
,因为它是回调函数,所以它变成了
talkStub=sinon.stub('newFunc','newAct',{data:'name')。yields({“status:“online”})
这正是我第一次使用的,但我得到了这个错误,TypeError:试图将未定义的属性newAct包装为函数“哦,对不起,我的错误,我粘贴了错误的代码段。您的代码几乎正确,但转换为
yields
,例如
talkStub=sinon.stub()。withArgs('newFunc','newAct',{data:'name')。yields(null,{“status”:“online”})