首页 > 解决方案 > 使用 Sinon.js 模拟 Jquery 事件

问题描述

我有以下 javascript 模块,当用户单击返回顶部按钮时,它会动画并将页面移动到顶部。

    const jsdom = require("jsdom");
    const { JSDOM } = jsdom;
    const { window } = new JSDOM(`...`);
    var $ = require("jquery")(window);
    
    const BackToTop = (function () {
      var baclTop = () => {
        $(".back").on("click", BackToTop.animate);
      };
      var animate = function () {
        $("html, body").animate({ scrollTop: "0" }, 1000);
      };
    
      return {
        baclTop,
        animate,
      };
    })();
    
    module.exports = BackToTop;

我使用 mocha 和 sinon.js 编写了以下测试用例,但出现以下错误

const BackToTop = require("../src/backToTop");
const sinon = require("sinon");
const jsdom = require("jsdom");
const document = new jsdom.JSDOM("<html></html>", {});
const window = document.defaultView;
global.document = document;
global.window = window;
const { expect } = require("chai");

describe("Name of the group", () => {
  it("should ", (done) => {
    $("body").append("<div class='sd-back-to-top'>hello world</div>");
    const operation = sinon.spy(BackToTop, "animate");

    $(".back").trigger('click');
    BackToTop.baclTop();
    expect(operation.callCount).to.be.eq(1);
    done();
  });
});
AssertionError: expected 0 to equal 1
    at Context.<anonymous> (test\backToTop.spec.js:17:39)
    at processImmediate (internal/timers.js:461:21)

+ expected - actual

-0
+1

我已经尝试了很多文章,但没有运气

提前致谢!

标签: javascriptjquerymocha.jssinon-chai

解决方案


BackToTop模块有两个私有(作用域)函数:baclTopanimate.

当您公开它们时,您正在声明附加到模块的另外两个函数:

return {
    baclTop, // shortcut for baclTop: baclTop
    animate,
}

所以当你创建 spy 时,sinon 会将函数暴露的函数包装在返回块中:

const operation = sinon.spy(BackToTop, "animate");

但是,调用BackToTop.baclTop()this 时会调用“内部”版本的animate函数,而 sinon 无法拦截此调用。

你不能这样做,你必须以可测试的方式重写你的代码,或者只监视你直接调用的函数。


推荐阅读