单元测试主干模型保存句柄



我有一个使用submit方法的视图。如何编写单元测试以检查事件是否在以下代码中触发

submit:(event) ->
MyModel.save(null, {
success: (model, response)=>
@trigger('saveSuccess', response)
})

注意:我不想检查成功是否被称为

尝试:

it 'Should trigger events on save', (done) ->
originalSave = MyModel.save
triggerSpy = sinon.spy()
MyModel.on('rating:saveSuccess', triggerSpy)
stub = sinon.stub(MyModel, "save", ->
successSpy = sinon.spy(arguments[1].success)
originalSave.apply(MyModel, arguments);
# want to call this line in the successSpy callback
expect(triggerSpy.callCount).to.equal(1);
done()
)
MyView.submit({})   
expect(stub).to.have.been.called 

编辑第二次尝试(有效,但不确定其正确方式)

it 'Should trigger events on save', (done) ->
triggerSpy = sinon.spy()
MyView.on('saveSuccess', triggerSpy)
stub = sinon.stub(MyModel, "save", ->
arguments[1].success()
expect(triggerSpy.callCount).to.equal(1);
done()
)
MyView.submitReval({})  
expect(stub).to.have.been.called

单元测试时,需要对所涉及的单元做出决定。考试何时何地开始和结束。您可能会决定,重要的是代码覆盖率,就像伊斯坦布尔这样的工具所计算的那样。

您的第一个示例将运行Model.save代码,立即断言事件已被触发。这意味着您将拥有该功能的100%覆盖范围。但请记住,Model.save正在运行,您可能不希望覆盖模型。这可能不起作用,因为save操作不是同步的,因此断言在代码完成之前运行。如果你还没有使用sinon的fakeServer,那么你应该考虑一下

您的第二个示例截取Model.save并从不运行它。这将为您提供1行代码覆盖率(50%),但考虑到该处理程序只有一行代码,您需要以这种方式询问该测试是否有任何值。

如果你是一个单元测试纯粹主义者,并且希望这个单元测试只为被测试的函数增加覆盖范围,那么以下方法会起作用:

it 'Should trigger events on save', ->
triggerSpy = sinon.spy()
MyModel.on('saveSuccess', triggerSpy)
stub = sinon.stub(MyModel, "save", (attr, opts) ->
opts.success.apply(null, [this, {}])
)
MyView.submit({})   
expect(stub).to.have.been.called
expect(triggerSpy.callCount).to.equal(1)
expect(triggerSpy.args[0][0]).to.deep.equal({})

这提供了对函数的100%覆盖(仍然只有2行,但这就是函数)。现在它是同步的,Model.save没有被调用,而是被存根。它断言函数的最终输出,事件被触发。它还测试保存的响应是否包含在事件中。

如果你不是一个纯粹主义者,那么看看sinon的fakeServer。

最新更新