Testing 主干:如何在不直接测试回调的情况下测试要调用的默认值

Testing 主干:如何在不直接测试回调的情况下测试要调用的默认值,testing,backbone.js,coffeescript,functional-testing,preventdefault,Testing,Backbone.js,Coffeescript,Functional Testing,Preventdefault,假设我们有一个简单的主干视图,如下所示: class MyView extends Backbone.View events: 'click .save': 'onSave' onSave: (event) -> event.preventDefault() # do something interesting 我想测试当我用.save类在我的元素上单击时调用事件.preventDefault() 我可以测试我的回调

假设我们有一个简单的主干视图,如下所示:

class MyView extends Backbone.View

    events: 
        'click .save': 'onSave'

    onSave: (event) ->
        event.preventDefault()

        # do something interesting
我想测试当我用
.save
类在我的元素上单击
时调用
事件.preventDefault()

我可以测试我的回调函数的实现,就像这样(Mocha+Sinon.js):

我认为它不起作用,但这只是为了得到这个想法;编写正确的代码,这是可行的。我这里的问题是,这样我测试的是实现,而不是功能

所以,我的问题是:假设在我的
.save
元素上触发一个
点击
事件,我该如何验证

it 'prevents default submission', ->
    myView.$('.save').click()

    # assertion here ??

一如既往地感谢:)

所以您想测试在生成
单击事件时调用
预防默认值,对吗

你不能做一些类似的事情吗(在JavaScript中。我将把咖啡脚本作为练习;):

您可能希望在创建click事件之前调用
preventDefaultSpy.reset()
,以便调用计数不受其他事件的影响

我还没有测试过,但我相信它会起作用


编辑:换句话说,因为我的答案与你问题的一部分没有太大区别:我认为你的第一种方法是可以的。通过监视
Event.prototype
您不会调用
myView
,因此它更像是一个黑匣子,这可能会减轻您的一些顾虑。

所以您想测试在生成
单击
事件时调用
preventDefault
,对吗

你不能做一些类似的事情吗(在JavaScript中。我将把咖啡脚本作为练习;):

您可能希望在创建click事件之前调用
preventDefaultSpy.reset()
,以便调用计数不受其他事件的影响

我还没有测试过,但我相信它会起作用


编辑:换句话说,因为我的答案与你问题的一部分没有太大区别:我认为你的第一种方法是可以的。通过监视
Event.prototype
您不会调用
myView
,因此它更像是一个黑匣子,这可能会减轻您的一些顾虑。

尝试在视图的
$el
上添加一个侦听器,然后触发
单击
上的
。保存
,然后验证该事件没有出现在视图的元素中

var view = new MyView();
var called = false;
function callback() { called = true; }

view.render();

// Attach a listener on the view's element
view.$el.on('click', callback);

// Test
view.$('.save').trigger('click');

// Verify
expect(called).toBeFalsy();

尝试在视图的
$el
上添加一个侦听器,然后触发
单击
上的
。保存
,然后验证该事件没有出现在视图的元素上

var view = new MyView();
var called = false;
function callback() { called = true; }

view.render();

// Attach a listener on the view's element
view.$el.on('click', callback);

// Test
view.$('.save').trigger('click');

// Verify
expect(called).toBeFalsy();

虽然这应该可以很好地工作,但它依赖于实现来验证行为。我明白了,这是有意义的。虽然这应该可以很好地工作,但它依赖于实现来验证行为。我明白了,这是有意义的。您认为在这里插入一些虚拟元素来运行类似的测试有意义吗?比如添加
,然后在
myfoothatexistsonlyhere
添加带有回调的click事件?阅读您的代码时,我的第一个想法是“如果它不是因为其他原因冒泡怎么办?”比如如果另一个部分调用
preventDefault
。在你看来,这是不是太过分了?基本上,这就是这个测试应该做的。渲染视图时,应设置与所布置的结构相似的结构。如果您愿意,您可以将呈现的视图放到另一个父元素中,但对我来说,这似乎有些过分。我的意思是在视图呈现后添加这些虚拟元素,这样您就不必依赖于实际模板的结构,也不希望其他事件回调停止冒泡。例如,如果你的模板有
div.container>div.willstopeverything>div.save
单击。willstopeverything
在你的应用程序的其他地方被监听,而你却没有意识到。我明白了。如果视图的结构和行为如你所建议的那样,我会将我的测试配置为监听
。willstopeverything
div而不是视图的
$el
。作为测试的一部分,我不会覆盖视图的模板(或呈现的HTML)。您认为在这里插入一些虚拟元素来运行类似测试有意义吗?比如添加
,然后在
myfoothatexistsonlyhere
添加带有回调的click事件?阅读您的代码时,我的第一个想法是“如果它不是因为其他原因冒泡怎么办?”比如如果另一个部分调用
preventDefault
。在你看来,这是不是太过分了?基本上,这就是这个测试应该做的。渲染视图时,应设置与所布置的结构相似的结构。如果您愿意,您可以将呈现的视图放到另一个父元素中,但对我来说,这似乎有些过分。我的意思是在视图呈现后添加这些虚拟元素,这样您就不必依赖于实际模板的结构,也不希望其他事件回调停止冒泡。例如,如果你的模板有
div.container>div.willstopeverything>div.save
单击。willstopeverything
在你的应用程序的其他地方被监听,而你却没有意识到。我明白了。如果视图的结构和行为如你所建议的那样,我会将我的测试配置为监听
。willstopeverything
div而不是视图的
$el
。作为测试的一部分,我不会覆盖视图的模板(或呈现的HTML)。
var view = new MyView();
var called = false;
function callback() { called = true; }

view.render();

// Attach a listener on the view's element
view.$el.on('click', callback);

// Test
view.$('.save').trigger('click');

// Verify
expect(called).toBeFalsy();