Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用jasmine.js和sinon.js不会调用backbone.js单击事件间谍_Javascript_Jquery_Backbone.js_Jasmine_Sinon - Fatal编程技术网

Javascript 使用jasmine.js和sinon.js不会调用backbone.js单击事件间谍

Javascript 使用jasmine.js和sinon.js不会调用backbone.js单击事件间谍,javascript,jquery,backbone.js,jasmine,sinon,Javascript,Jquery,Backbone.js,Jasmine,Sinon,我正在尝试使用backbone.js、jasmine.js和sinon.js测试按钮点击。但是下面的测试用例失败了。我正在用间谍追踪它是否被呼叫。 你能帮我做这个吗 谢谢 新任务模板 <script id='new_task_template' type='text/template'> <input type='text' id='new_task_name' name='new_task_name'></input> <button type

我正在尝试使用backbone.js、jasmine.js和sinon.js测试按钮点击。但是下面的测试用例失败了。我正在用间谍追踪它是否被呼叫。 你能帮我做这个吗

谢谢

新任务模板

<script id='new_task_template' type='text/template'>
  <input type='text' id='new_task_name' name='new_task_name'></input>
  <button type='button' id='add_new_task' name='add_new_task'>Add Task</button>
</script>
describe("NewTaskView", function(){
  beforeEach( function(){    
    this.view = new T.views.NewTaskView();
    this.view.render();
  });

  it("should #add_new_task is clicked, it should trigger the addTask method", function(){
    var clickSpy = sinon.spy( this.view, 'addTask');
    $("#add_new_task").click();
    expect( clickSpy ).toHaveBeenCalled();
  });
});
茉莉花测试用例

<script id='new_task_template' type='text/template'>
  <input type='text' id='new_task_name' name='new_task_name'></input>
  <button type='button' id='add_new_task' name='add_new_task'>Add Task</button>
</script>
describe("NewTaskView", function(){
  beforeEach( function(){    
    this.view = new T.views.NewTaskView();
    this.view.render();
  });

  it("should #add_new_task is clicked, it should trigger the addTask method", function(){
    var clickSpy = sinon.spy( this.view, 'addTask');
    $("#add_new_task").click();
    expect( clickSpy ).toHaveBeenCalled();
  });
});
茉莉花产量

NewTaskView
  runEvents
    runshould #add_new_task is clicked, it should trigger the addTask method
      Expected Function to have been called.
表示您正在将单击事件绑定到视图的
this.el
-根元素,在您的情况下,该元素具有ID
新建任务部分
。您需要将它绑定到
#add_new_task
,我想这是您的“addtask”按钮-这应该可以修复它

events:{
    "click #add_new_task" : "addTask"
},
更新:


$(“#添加#新#任务”)找不到元素,因为视图未添加到文档DOM树中。使用
this.view.$('add#new_task')
它应该可以工作,因为它将在视图中存储的分离片段中搜索元素。

您的方法存在一些问题。首先,您监视您想要测试的类,这不是单元测试应该使用的方式,因为您测试的是类的内部逻辑,而不是它的行为。其次,这也是测试失败的原因,因为您没有将视图附加到DOM中。因此,要么将el附加到DOM,要么直接将click事件激发到el:
$(“#add_new_task”,this.view.el)。click()

顺便说一句,backbones创建元素和绑定事件的方式使得编写好的单元测试变得困难,因为您必须使用DOM和jquery。编写可测试代码的更好方法是始终将所有依赖项传递给构造函数,并且不要在代码中创建新实例,因为很难测试这些对象。因此,在您的例子中,将el对象作为jquery对象注入构造函数并在事件发生时手动注入会容易得多。通过这种方式,您可以在不依赖于DOM或jquery的情况下测试类

因此,在您的情况下,构造函数将如下所示:

initialize: function(){
   this.el.click(_.bind( this, 'addTask'));
}
还有你的测试:

var el = {click: function(){}};
spyOn( el, 'click');
new T.views.NewTaskView({el: el});
expect(el.click).toHaveBeenCalled(); //test the click event was bind
//call the function that was bind to the click event, 
//which is the same as trigger the event on a real DOM object
el.click.mostRecentCall.args[0]() 

毕竟,你必须决定什么方法适合你的需要。使用backbones helpers的更精简的代码或对jquery、DOM和backbone依赖性更小的更好的可测试代码。

问题是,在backbone已经将click事件直接绑定到addTask函数(它在构建视图期间执行此操作)之后,您添加了spy。所以你的间谍不会被召唤

在构建视图之前,请尝试将spy附加到视图的原型。像这样:

this.addTaskSpy = sinon.spy(T.views.NewViewTask.prototype, 'addTaskSpy');
this.view = new T.views.NewTaskView();
然后记住将其移除:

T.views.NewViewTask.prototype.addTaskSpy.restore()

视图在DOM中的何处呈现自身?模板是否在规范中可用?Jasmine spec runner的DOM中可能不存在“添加新任务”按钮,因此
$(“添加新任务”)。单击()无效。如果您确定视图是使用正确的模板呈现的,那么可以使用NewTaskView的元素作为jquery函数的上下文:
$('add#new_task',this.view.el)。单击()。我想这个问题已经在这里得到了回答:事实上,我也有这个“单击#添加#新"任务”的问题,事件被触发,因为我在addTask方法中有console.log行。但是expect(spy).tohavebeencall()失败;可能是我的绑定错误?如果#add_new_任务不在此视图中,它不是绑定在错误的位置吗?jQuery的工作方式是搜索附加到文档的DOM树,但是如果您自己不将主干视图元素附加到DOM树,它就不在那里。这就是为什么需要使用主干jQuery find(Backbone.View$方法),它将搜索的上下文设置为视图的
el
,从而可以在尚未连接到DOM树的DOM中进行搜索#add_new_任务正好在视图中-只是视图不在文档中-它只是保存在内存中,等待插入执行
$(body).append(this.view.el)
渲染后,您将看到它应该可以工作,而不必将$('add_new_任务')更改为
this.view.$('add_new_任务')
(或者您可以编写它
$('add#u new_task',this.view.el)
,如果您愿意的话)。这是100%正确的行为。
jasmine jquery
助手可以帮助您处理设备:jasmine不是一个单元测试框架-它是BDD框架,他所做的非常好-测试一个行为不确定您的观点。监视您想要测试的类没有多大意义。因为这不是您的类的行为l一个特定的函数本身。更改此函数的名称将破坏测试,但不会破坏行为。另一个想法是,我认为最好尽可能多地模拟依赖项。使用依赖项注入会更容易,因为您不必在测试前加载夹具,对其触发单击事件并在战后清理ds.这个答案应该被接受。谢谢,这太令人头痛了!完全有道理!谢谢!:)我不清楚的是:如果我只想监视原型的一个实例,为什么我需要监视原型。这不可能吗?这很有效。比必须更改代码才能进行测试要好得多。+1谢谢!只是一个小注释,因为要监视的方法是addTask,它应该是:
this.addTaskSpy=sinon.spy(T.views.NewViewTask.prototype,'addTask')
T.views.NewViewTask.prototype.addTask.restore()