【问题标题】:how to mock jquery calls from within a function using jasmine and sinon如何使用 jasmine 和 sinon 从函数内模拟 jquery 调用
【发布时间】:2013-08-11 17:12:43
【问题描述】:

首先,这是一项工作要求。如果不能以这种方式完成,我需要一个很好的论据。

我必须使用 jasmine 和 sinon 测试我们的骨干项目。我不知道如何在函数中模拟 jquery 调用。我有一个这样的函数(清理了一点以丢弃无关的调用):

Project.Views.FormView = Backbone.View.extend({
  sidenavClicked: function(event){



    var sidenav_id = $(event.target).attr('id').split('m')[1];
    var sidenav_num = sidenav_id.split('m')[1];

    var form_id = $('div.active form').attr('id');
    var form_num = form_id.split('m')[1];

    //code for fast scrolling
    this.slideTo(form_num-1, sidenav_num-1);

    return false;
  },
  ...
});

现在我只是想测试一下 slideTo() 是否被调用这是我的茉莉花规格

describe("Form", function(){
    describe("Carousel", function(){

    it("should call slideTo when navbar is clicked", function(){
        var spy = sinon.spy();
        var formView = new Project.Views.FormView({ el : $('#main'), id : 1});
        formView.bind('slideTo', spy);

        var event = {};
        event.target = "<div id='form1'></div>";

        formView.sidenavClicked(event);
    });
});

错误信息是:TypeError: form_id is undefined in file: .../src/main/webapp/js/views/FormView.js

据我所知,这是因为没有可供 jQuery 匹配的文档。如何让 form_id 有值?

实际的代码确实有效,并且确实做了它应该做的事情。

更新:html 看起来像这样:

<html>
<body>
    <div id="main">
        <ul id="carousel-navbar">
            <li><a id="navlink-form1">Text</a></li>
            ...
        </ul>
        <div id="formCarousel" class=" carousel slide" >
            <div class="active first item">
                <form id="form1" name="question1">
                    ...
                </form>
            </div>
            ...
        </div>
    </div>
</body>
</html>

澄清不完全是这样(实际是 442 行),但结构应该是相关的同义词。

【问题讨论】:

  • 在里面。我会更新答案。
  • 如果它在el 内,那么你应该使用this.$() 而不是$(),这甚至可以解决你的问题(但我对你的堆栈了解不够肯定知道)。
  • 是的,我已经尝试过了。$()。问题是 jasmine 测试没有附加到我知道的任何 html 上,因此 jQuery 选择器没有选择任何内容。如果这不正确,请告诉我。
  • 服务器上运行的代码运行正常。
  • 你能把上面显示的 html 传递给 FormView 构造函数吗?只要您随后使用 this.$(),它就应该对您的模拟 HTML 起作用。

标签: jquery backbone.js jasmine sinon


【解决方案1】:

这可能看起来有点幼稚,但我还是会指出来。

在我看来,您实际上并没有在任何地方渲染视图。我这么说只是因为您发布的代码都没有在视图上调用.render(),而且我看不到任何暗示它在幕后发生的事情,这可能解释了为什么 JQuery 调用的行为方式是这样的。

在 Jasmine 规范中渲染视图通常很简单:

beforeEach(function () {
  // some element you want to render your view into
  $('#testbed').html(view.render().el);
});

form_id 可能未定义,因为您要查找的元素不在 DOM 中。你真的能从函数中找到那个元素吗?以及从测试本身?

(另外,由于该函数绑定到一个事件,我个人认为通过触发该事件来调用它可能更有意义 - 例如.click() 或 div 上的任何内容 - 而不是显式调用它。)

【讨论】:

  • 我已经尝试过这样的方法,但当不按自然方式调用所有内容时,渲染它仍然存在一些问题。
【解决方案2】:

问题是您要查找的元素未附加到 DOM。您必须在调用函数之前添加它:

it("should call slideTo when navbar is clicked", function(){
    var spy = sinon.spy();
    var formView = new Project.Views.FormView({ el : $('#main'), id : 1});
    formView.bind('slideTo', spy);
    $('body').append('<div class="active"><form id="form1" /></div>');


    var event = {};
    event.target = "<div id='form1'></div>";

    formView.sidenavClicked(event);
});

还有一些插件可以更轻松地使用 jasmin 处理灯具:jasmine-fixture 或 jasmine-dom

【讨论】:

  • 我尝试了许多不同的添加方式。这种方式虽然可行。我找到的最好的方法。这种方式的问题显然是(对于未来的用户)现在来自 jasmine 规范的 html 有额外的 html(它只需要在每次测试结束时清理),而稍微大一点的问题意味着 this.$()不能使用(如果可能的话,你应该使用带主干的 jquery 调用的方式)。感谢您的帮助,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
  • 2017-10-24
  • 1970-01-01
  • 2021-06-18
  • 2013-08-15
相关资源
最近更新 更多