显示模块替代或变体以进行测试

Revealing Module Alternative or Variation for Testing

本文关键字:测试 模块 显示      更新时间:2023-09-26

概述

我已经使用揭示模块模式几个月了,我正在寻找此模式的替代或变体,以解决我目前在事件处理程序和可测试性方面遇到的两个问题。 我知道我可以想出一些我下面的组合来解决我的问题,但我希望找到一个干净的替代方案,我可以始终如一地使用来解决我目前的两个问题。

揭示模块模式

所以在这个例子中,我对事件处理程序没有问题,但我不能模拟对函数的调用在要单独测试的函数中:

var Lion = (function () {
  // Reference to rawr works as expected when the click event is triggered
  function watch() {
    document.addEventListener('click', rawr);
  }
  function rawr() {
    console.log('rawr');
  }
  function attack() {
    console.log('attack');
  }
  /*
   * Can't test goCrazy() in isolation.  Mocking rawr() and attack()
   * has no effect as demonstrated below.
   */
  function goCrazy() {
    rawr();
    attack();
    // Important "crazy" logic
  }
  return {
    watch: watch,
    rawr: rawr,
    attack: attack,
    goCrazy: goCrazy
  };
}());
module.exports = Lion;

示例测试用例(茉莉花)

describe('Mock Check', function () {
  it('should mock rawr() and attack() and test only goCrazy logic', function () {
    var lion = require('Lion');
    spyOn(lion, 'rawr').and.reutrnValue(true);  
    spyOn(lion, 'attack').and.reutrnValue(true);  
    var crazy = lion.goCrazy();
    expect(lion.rawr).toHaveBeenCalled(); // <-- Fails
    expect(lion.attack).toHaveBeenCalled(); // <-- Fails
    // can't test goCrazy() logic in isolation :(
  });
});

使用this代替相同的模块,并使用new调用

在此示例中,我可以成功地模拟对函数内函数的调用,但是如果我尝试添加事件处理程序,则在触发事件时this变得undefined

var Lion = function () {
  // Reference to 'this' becomes undefined when event is triggered
  this.watch = function () {
    document.addEventListener('click', this.rawr);
  }
  this.rawr = function () {
    console.log('rawr');
  }
  this.attack = function () {
    console.log('attack');
  }
  /*
   * Can successfully test goCrazy() in isolation by being able to mock 
   * rawr() and attack() as needed
   */
  this.goCrazy = function () {
    this.rawr();
    this.attack();
    // Important "crazy" logic
  }
};
module.exports = Lion;

示例测试用例(茉莉花)

describe('Mock Check', function () {
  it('should mock rawr() and attack() and test only goCrazy logic', function () {
    var Lion = require('Lion');
    var lion = new Lion();
    spyOn(lion, 'rawr').and.reutrnValue(true);  
    spyOn(lion, 'attack').and.reutrnValue(true);  
    var crazy = lion.goCrazy();
    expect(lion.rawr).toHaveBeenCalled(); // <-- Success
    expect(lion.attack).toHaveBeenCalled(); // <-- Success
    // testing goCrazy logic in isolation :)
  });
});

谢谢你的时间。 如果需要任何澄清,请告诉我,我会修改我的帖子。

这里的实际问题是,事件处理程序丢失了当前对象的上下文。你可以像这样绑定它

document.addEventListener('click', this.rawr.bind(this));

这将确保无论何时调用rawrrawr内部的this都与您创建的lion对象相对应。