Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/42.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 即使正在调用被监视的函数,Sinon spy也会失败_Node.js_Mocha.js_Sinon_Chai - Fatal编程技术网

Node.js 即使正在调用被监视的函数,Sinon spy也会失败

Node.js 即使正在调用被监视的函数,Sinon spy也会失败,node.js,mocha.js,sinon,chai,Node.js,Mocha.js,Sinon,Chai,我很难理解为什么sinon spy对我来说失败了,即使我所监视的函数在测试期间被调用(我用一些简单的控制台日志记录证明了这一点) 假设我有以下几点: const nock = require('nock'); const sinon = require('sinon'); const MyModule = require('../index.js'); describe('When calling DoStuff succeeds in making the xhr call', () =>

我很难理解为什么sinon spy对我来说失败了,即使我所监视的函数在测试期间被调用(我用一些简单的控制台日志记录证明了这一点)

假设我有以下几点:

const nock = require('nock');
const sinon = require('sinon');
const MyModule = require('../index.js');
describe('When calling DoStuff succeeds in making the xhr call', () => {
        before(() => {
          nock(apiHostName)
            .post('/some-path')
            .reply(200, { foo: 'bar' });
        });
        it('should call doOtherStuff', async () => {
          const spy = sinon.spy(MyModule, 'doOtherStuff');
          await MyModule.DoStuff();
          sinon.assert.calledOnce(spy);
        });
      });
index.js

let MyModule = require('./src/index.js');

MyModule = new MyModule();

module.exports = {
  DoStuff: MyModule.DoStuff,
  doOtherStuff: MyModule.doOtherStuff,
};
const MyModule = function MyModule() {

  const self = this;

  self.doOtherStuff = function doOtherStuff() {
    console.log('doOtherStuff called!!!')
  }

  self.DoStuff = async function DoStuff() {
    const xhr = self.axiosInstance();
    await xhr.post()
      .then((res) => {
        self.doOtherStuff(res.data);
      })
      .catch((_err) => {
        console.log(_err);
      });
  };
}

module.exports = MyModule;
src/index.js

let MyModule = require('./src/index.js');

MyModule = new MyModule();

module.exports = {
  DoStuff: MyModule.DoStuff,
  doOtherStuff: MyModule.doOtherStuff,
};
const MyModule = function MyModule() {

  const self = this;

  self.doOtherStuff = function doOtherStuff() {
    console.log('doOtherStuff called!!!')
  }

  self.DoStuff = async function DoStuff() {
    const xhr = self.axiosInstance();
    await xhr.post()
      .then((res) => {
        self.doOtherStuff(res.data);
      })
      .catch((_err) => {
        console.log(_err);
      });
  };
}

module.exports = MyModule;
我的测试如下:

const nock = require('nock');
const sinon = require('sinon');
const MyModule = require('../index.js');
describe('When calling DoStuff succeeds in making the xhr call', () => {
        before(() => {
          nock(apiHostName)
            .post('/some-path')
            .reply(200, { foo: 'bar' });
        });
        it('should call doOtherStuff', async () => {
          const spy = sinon.spy(MyModule, 'doOtherStuff');
          await MyModule.DoStuff();
          sinon.assert.calledOnce(spy);
        });
      });
我在我的测试运行程序输出中看到了doOtherStuff函数输出中的控制台日志,但是测试失败,说spy被调用了零次

我想知道这是否与我正在测试的代码的异步性质有关,但我已经确保在测试中使用async/await来实现。我一定是做了什么蠢事,我哪里做错了

谢谢

更新

因此,我尝试将函数剥离回更基本的内容,现在有以下内容:

const MyModule = function MyModule() {

  const self = this;

  self.doOtherStuff = function doOtherStuff() {
    console.log('doOtherStuff called!!!')
  }

  self.DoStuff = function DoStuff() {
    self.doOtherStuff();
  };
}

module.exports = MyModule;
因此,这将排除我可能遇到的任何异步/等待问题

但即使在运行以下简单测试时,间谍也不会被调用:

const MyModule = require('../index.js');

it('should call doOtherStuff', () => {
  const spy = sinon.spy(MyModule, 'doOtherStuff');
  MyModule.DoStuff();
  sinon.assert.calledOnce(spy);
});
如果我监视
console.log
,它就会通过。我一定是误解了一个非常基本的原则,但我不知道它是什么

这是否与我的
模块导出的声明方式有关?因此,即使我试图在我的
index.js
(the
doOtherStuff:MyModule.doOtherStuff
)中监视顶级导出,但在我的测试中调用DoStuff时,这并不是实际在内部调用的吗

发行
spy
中包装的属性不是被调用的属性

细节
sinon.spy
获取一个对象和一个属性名,并将函数包装在spy中该属性名处

在本例中,对象是
index.js
的模块导出

模块导出是一个具有两个属性的对象,它们指向在
index.js
中创建的内部
MyModule
实例上的方法。因此,该对象的
doOtherStuff
属性现在是
spy
,而
DoStuff
属性仍然只是内部
MyModule
实例的
DoStuff
属性的引用

然后,当测试调用
MyModule.DoStuff()
时,它调用内部
MyModule
实例的
DoStuff
属性,该实例调用登录到控制台的内部
MyModule
实例的
doOtherStuff
属性

关键是内部
MyModule
实例的
doOtherStuff
属性被直接调用,而
index.js
导出的对象的
doOtherStuff
属性从未被调用

然后,由
index.js
导出的对象的
doOtherStuff
属性上的
spy
正确地断言它被调用了0次

解决方案 确保在实际调用的属性上创建了
spy

在这种情况下,最简单的方法是直接从
index.js
导出
MyModule
实例:

let MyModule = require('./src/index.js');

MyModule = new MyModule();

module.exports = MyModule;
现在,当创建
spy
时,它直接在内部
MyModule
实例的
doOtherStuff
属性上创建,并将正确报告它被调用过一次。

问题
spy
中包装的属性不是被调用的属性

细节
sinon.spy
获取一个对象和一个属性名,并将函数包装在spy中该属性名处

在本例中,对象是
index.js
的模块导出

模块导出是一个具有两个属性的对象,它们指向在
index.js
中创建的内部
MyModule
实例上的方法。因此,该对象的
doOtherStuff
属性现在是
spy
,而
DoStuff
属性仍然只是内部
MyModule
实例的
DoStuff
属性的引用

然后,当测试调用
MyModule.DoStuff()
时,它调用内部
MyModule
实例的
DoStuff
属性,该实例调用登录到控制台的内部
MyModule
实例的
doOtherStuff
属性

关键是内部
MyModule
实例的
doOtherStuff
属性被直接调用,而
index.js
导出的对象的
doOtherStuff
属性从未被调用

然后,由
index.js
导出的对象的
doOtherStuff
属性上的
spy
正确地断言它被调用了0次

解决方案 确保在实际调用的属性上创建了
spy

在这种情况下,最简单的方法是直接从
index.js
导出
MyModule
实例:

let MyModule = require('./src/index.js');

MyModule = new MyModule();

module.exports = MyModule;

现在,当创建
spy
时,它将直接在内部
MyModule
实例的
doOtherStuff
属性上创建,并将正确报告它被调用过一次。

看起来您在监视
ALClient
,而不是
MyModule
?是的,对不起,当我把这个代码片段放上去时,这是一个输入错误。我已经纠正了这一点,但原来的问题仍然存在。谢谢你的意思是要先创建MyModule的实例吗?在您的示例中,
MyModule
没有可以监视的
DoStuff
属性,也没有
doOtherStuff
属性。在显示的代码中,您应该看到Sinon引发的“试图包装未定义的属性doOtherStuff”异常:。但是,如果您创建了
MyModule
的实例,它可以正常工作:在测试规范文件的开头,我确实需要模块中的
require
,因此这些属性在测试运行时可用。我没有在我的测试规范代码段中显示require语句,我现在已经添加了它。我怀疑