【问题标题】:How to mock/stub callback function with sinon.js?如何使用 sinon.js 模拟/存根回调函数?
【发布时间】:2013-08-14 20:49:13
【问题描述】:

我想用 QUnit 和 Sinon.Js 编写单元测试。我有一个应用程序,用户可以在其中单击一个按钮,然后出现一个模式对话框来处理下载一些文件。用户可以关闭对话框,它会触发一个方法来运行以重置一些变量。我的测试代码:

$(function() {
    $.fn.copy_button = function(){};

    ln_download_view = new DownloadModalView();
    ln_download_view.modal = {'modal': function() {}};
    var download_modal_dialog = $('.download-modal');
    download_modal_dialog.modal = function(param){};
    var modal_mock = sinon.mock(ln_download_view.modal);
    var download_modal_dialog_mock = sinon.mock(download_modal_dialog);

    //Should be inserted, because ln_download_view.modal is mocked
    //The close button even handler
    $('#btn_close_modal').click(function(){
        download_modal_dialog.modal('hide');
    });

    //Dirty stuff to do after the window closes
    //Basicly the click triggers this event handler
    $('.download-modal').on('hide',function() {
        window.clearInterval(window.periodicalTimer);
    });

    $('div .option-container').click(function() {
        if(!$(this).hasClass("selected-option"))
        {
            $('div #option-presenting').toggleClass("selected-option");
            $('div #option-editing-and-presenting').toggleClass("selected-option");

            $('.image').toggle();
        }
    });

    module("views");
    test("Download modal dialog is displayed", function(){
        var modal_triggered = modal_mock.expects("modal").once();
        ln_download_view.handleDownloadClick();
        ok(modal_triggered.verify());
    });

    test("Download modal dialog is closed",function(){
        var modal_triggered = download_modal_dialog_mock.expects("modal");
        $('#btn_close_modal').trigger('click');
        ok(modal_triggered.verify());
    });
});

我不明白的是,我该如何测试/模拟/存根这段代码:

$('.download-modal').on('hide',function() {
    window.clearInterval(window.periodicalTimer);
});

我还没有深入了解。

【问题讨论】:

    标签: javascript qunit sinon


    【解决方案1】:

    您不能模拟/存根匿名函数。但是您可以进行重构并存根/模拟命名的回调。

    $('.download-modal').on('hide', onHide);
    
    var onHide = function() {
        window.clearInterval(window.periodicalTimer);
    };
    
    // ...
    
    sinon.stub(onHide);
    

    【讨论】:

    • 哦,我明白了。还有一件事。当点击发生时,应该调用 on hide 之后。我的测试应该期待两个函数调用,一个是模态的,一个是 onHide,但是模态应该触发 onHide。但是因为模态被模拟了,所以它不起作用。将 download_modal_dialog.modal 覆盖为与调用 onHide 的函数相等是否很好?谢谢!
    • 然后使用sinon.spy,所以它会按预期工作+ spy 它被调用。
    • 谢谢,我成功了。但是还有一个问题?调用 onHide() 和调用 on_hide_spy.call() 有什么区别。 (var on_hide_spy = sinon.spy(onHide);)
    • .call 只允许您在特定上下文中调用该函数。 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    • 以上内容不再适用于 Sinon 2.3.8 var a = function() {}; var spy = si.spy(this, a); 抛出:TypeError: Attempted to wrap undefined property function () {} as function
    【解决方案2】:

    这是我的方法:

    在每个之前,创建一个不做任何事情的函数:

    var doNothing = function(){};
    

    然后在你的测试中,监视它:

    var spy = sinon.spy(this, 'doNothing');
    

    然后调用你的方法,传入一个触发 doNothing 方法的回调:

      var self = this;
      whatever.doSomethingAwesome(
      {
        finished: function(){
          self.doNothing();
        }
      });
      expect(spy.callCount).toEqual(1);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-01
      • 2015-12-09
      • 1970-01-01
      • 2014-06-18
      • 2018-03-06
      • 2018-10-31
      • 1970-01-01
      相关资源
      最近更新 更多