使用backbone.validation测试骨干模型验证 - 间谍永远不会被调用

时间:2012-11-03 08:20:21

标签: ruby-on-rails validation backbone.js coffeescript jasmine

我正在使用backbone.validation来验证我的骨干模型,并采用TDD方法来完成我的工作。不幸的是,在测试实际需要的字段时,我似乎无法调用我的间谍。

我一直在关注Testing Backbone applications with Jasmine and Sinon上的教程 除非他用"error"注册他的间谍,我尝试用"invalid"注册我的间谍。这是因为我认为backbone.validation使用无效/有效的回调,而不是如自述文件的事件部分所述。

我的问题是我收到错误,说我的间谍从未被调用过。我尝试将绑定更改回错误/保存,但仍然没有运气。

我的代码如下:

class Event extends Backbone.Model
    url: ->
      '/events' + (if @isNew() then '' else '/' + @id)

    validation:
      title:
        required: true
      start_date:
        required: true
      end_date:
        required: true
      description:
        required: true

然后我按如下方式定义测试:

describe "Event", ->
  beforeEach ->
    @title = "Foo"
    @description = "Bar"
    @start_date = new Date
    @end_date = new Date


    @event = new CPP.Models.Event {
      title: @title
      description: @description
      start_date: @start_date
      end_date: @end_date
    }

  describe "when saving required fields", ->
    beforeEach ->
      @error_spy = sinon.spy();
      @event.bind('invalid', @error_spy)

    it "should not save when title is empty", ->
      @event.save 'title': ""
      expect(@error_spy).toHaveBeenCalledOnce();

    it "should not save when start_date is empty", ->
      @event.save 'start_date': ""
      expect(@error_spy).toHaveBeenCalledOnce();

    it "should not save when end_date is empty", ->
      @event.save 'end_date': ""l
      expect(@error_spy).toHaveBeenCalledOnce();

    it "should not save when description is empty", ->
      @event.save 'description': ""
      expect(@error_spy).toHaveBeenCalledOnce();

    it "should not save when location is empty", ->
      @event.save 'location': null
      expect(@error_spy).toHaveBeenCalledOnce();

  describe "when saving optional fields", ->
    beforeEach ->
      @success_spy = sinon.spy();
      @event.bind('valid', @success_spy)

    it "should save when deadline is empty", ->
      @event.save 'deadline': ""
      expect(@success_spy).toHaveBeenCalledOnce();

然而,当我运行我的测试时,我似乎得到Error: Expected Function to have been called once.所有这些测试,并且在进一步检查@event对象时,我发现间谍永远不会被调用。

我认为这可能与模型原型的验证混合有关 _.extend(Backbone.Model.prototype, Backbone.Validation.mixin);在backbone.validation自述文件中定义,但我似乎无法使其工作。

我已经看过Why is this sinon spy not being called when I run this test?这个问题,但是我把这个答案合并到我的代码中也没有运气。

如果有人能告诉我我做错了什么,我将非常感激!

固定 我设法修复我的代码如下: (1)我将_.extend Backbone.Model::, Backbone.Validation.mixin添加到我的应用程序中

(2)然后我按照this question中给出的建议将我的间谍绑定在初始化上。代码现在看起来如下: 该模型:     class Event扩展了Backbone.Model         网址: - >           '/ events'+(如果@isNew()然后''else'/'+ @id)

    validation:
      title:
        required: true
      start_date:
        required: true
      end_date:
        required: true
      description:
        required: true

测试:

describe "Event", ->
  beforeEach ->
    @title = "Foo"
    @description = "Bar"
    @start_date = new Date
    @end_date = new Date

  describe "when saving required fields", ->
    beforeEach ->
      spy = @error_spy = sinon.spy();
      init = CPP.Models.Event::initialize
      CPP.Models.Event::initialize = ->
        spy(@, "validated:invalid")
        init.call this

      @event = new CPP.Models.Event {
        title: @title
        description: @description
        location: @location
        start_date: @start_date
        end_date: @end_date
      }

    it "should not save when title is empty", ->
      @event.save 'title': ""
      expect(@error_spy).toHaveBeenCalledOnce();

    it "should not save when start_date is empty", ->
      @event.save 'start_date': ""
      expect(@error_spy).toHaveBeenCalledOnce();

    it "should not save when end_date is empty", ->
      @event.save 'end_date': ""l
      expect(@error_spy).toHaveBeenCalledOnce();

    it "should not save when description is empty", ->
      @event.save 'description': ""
      expect(@error_spy).toHaveBeenCalledOnce();

    it "should not save when location is empty", ->
      @event.save 'location': null
      expect(@error_spy).toHaveBeenCalledOnce();

  describe "when saving optional fields", ->

    beforeEach ->
      spy = @success_spy = sinon.spy();
      init = CPP.Models.Event::initialize
      CPP.Models.Event::initialize = ->
        spy(@, "validated:valid")
        init.call this

      @event = new CPP.Models.Event {
        title: @title
        description: @description
        location: @location
        start_date: @start_date
        end_date: @end_date
      }

    it "should save when deadline is empty", ->
      @event.save 'deadline': ""
      expect(@success_spy).toHaveBeenCalledOnce();

2 个答案:

答案 0 :(得分:2)

您是否检查过您是否包含了添加验证混合的代码?

如果您希望能够在整个应用程序中绑定到模型中的已验证事件而不是特定视图,那么您需要通过编写

来添加mixins
_.extend(Backbone.Model.prototype, Backbone.Validation.mixin)

可以使用coffeescript作为

在您的应用程序中编写
_.extend Backbone.Model::, Backbone.Validation.mixin

在您的主Backbone应用程序文件中添加此代码。

完成此操作后,您的间谍问题可能与this question相关联 - 在绑定任何事件处理程序之前,您需要在正确的时间检查您是否是绑定间谍。上一个链接中的解决方案是通过挂钩初始化来实现的。

答案 1 :(得分:0)

我认为你只是绑定错误的事件。来自fine manual

  

<强>验证

     

执行验证后会触发validated事件,无论是否成功。 isValidtruefalse,具体取决于验证结果。

model.bind('validated', function(isValid, model, errors) {
  // do something
});
     

<强>验证:有效

     

执行成功验证后会触发validated:valid事件。

model.bind('validated:valid', function(model) {
  // do something
});
     

<强>验证:无效

     

执行不成功的验证后会触发validated:invalid事件。

model.bind('validated:invalid', function(model, errors) {
  // do something
});

因此,没有'invalid'事件,但有一个'validated:invalid'事件。试试这个:

@event.bind('validated:invalid', @error_spy)