繁体   English   中英

存根ES6 EventEmitter类函数

[英]Stub a ES6 EventEmitter class function

我有一个扩展EventEmitter的依赖项类,我需要测试使用此依赖项的函数如何根据触发的事件做出反应。 如何对EventEmitter类的函数进行存根?

依赖类

const EventEmitter = require('events');

class FooBar extends EventEmitter {

  constructor() {
    super();

    this.doingSomething = false;
  }

  doSomething() {
    if (this.doingSomething === false) {
      this.doingSomething = true;
      this.emit('startedDoingSomething');
    }
    else {
      this.emit('alreadyDoingSomething');
    }
  }
}

module.exports = FooBar;

被测模块

let Foobar = require('FooBar');
let fooBar = new FooBar();

exports.myFunction = () => {
  // Set up listeners
  fooBar.once('startedDoingSomething', () => {
    fooBar.removeAllListeners();
    // Some functionality
    console.log('Started Doing Something');
  });

  fooBar.once('alreadyDoingSomething', () => {
    fooBar.removeAllListeners();
    // Some functionality
    console.log('Already Doing Something');
  });

  // Call the event-emitting function
  fooBar.doSomething();
};

// Other functions that use fooBar

我正在使用Sinon来创建存根,但是我无法对有效发出事件的类函数进行存根。 我根据[Feature request]存根发出的内容对测试进行了建模,但是由于被存根的事件发射器依赖项是一个类,因此不得不进行一些修改。

测试

let chai = require('chai');
let sinon = require('sinon');
let FooBar = require('FooBar');
let dependentModule = require('./dependentModule');

describe('Dependent Module', () => {
  it('alreadyDoingSomething', () => {
    sinon.stub(FooBar.prototype, 'pause', () => {
      FooBar.prototype.emit('alreadyDoingSomething');
    });

    // Assertion statements here
    expect(dependentModule.myFunction()).to...
  });
});

即使正在调用存根函数,该方法实际上也不会发出事件。

测试中的第13行,它调用dependentModule.myFunction()

然后它跳到被测从属模块的第5行

然后在受测从属模块的第19行中,它调用fooBar.doSomething()

然后跳到Dependency Class中的第12行,那里this.doingSomething为false,因此它发出了startedDoingSomething

然后,它跳到“受测模块”中的第7行,它调用fooBar.removeAllListeners(); ,这意味着在同一文件的第34行注册的事件处理程序也将被删除。

这是真的吗?

现在,假设第7行“受测模块”中的fooBar.removeAllListeners已被注释掉。

然后在Test的第13行之后,它调用FooBar.prototype.pause ,然后依次调用FooBar.prototype.emit('alreadyDoingSomething');

问题在于,当FooBar.prototype.emit时, this在上下文中不等于在受测模块中的第2行中声明的fooBar (等于FooBar.prototype

所以FooBar.prototype.emit('alreadyDoingSomething'); 不会触发在受测模块中第12行中定义的事件处理程序。

我们将需要找到一种方法来调用fooBar.emit('alreadyDoingSomething')

但这是不可能的,因为除非使用诸如rewire之类的库,否则永远不会导出fooBar

现在假设我们添加了exports.fooBar = fooBar; 到被测相关模块的末尾。

并且我们还将Test中的第9行更改为this.emit('alreadyDoingSomething')这很重要,因为我们需要在调用this.emit('alreadyDoingSomething')时需要上下文作为实例,在我们的例子中是fooBar

现在在测试中,当调用dependentModule.fooBar.pause()时,将触发一个“已经开始做事”。

现在,您应该在控制台中看到Already Doing Something

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM