Rspec2测试before_validation方法

时间:2011-09-09 11:35:04

标签: ruby-on-rails ruby-on-rails-3 unit-testing rspec rspec2

我有以下内容删除特定属性的空格。

#before_validation :strip_whitespace

protected
  def strip_whitespace
    self.title = self.title.strip
  end

我想测试一下。现在,我试过了:

it "shouldn't create a new part with title beggining with space" do
   @part = Part.new(@attr.merge(:title => " Test"))
   @part.title.should.eql?("Test")
end

我错过了什么?

2 个答案:

答案 0 :(得分:13)

在保存对象或手动调用valid?之前,验证不会运行。您的before_validation回调未在当前示例中运行,因为您的验证永远不会被检查。在您的测试中,我建议您在检查标题是否已更改为预期之前运行@part.valid?

应用程序/模型/ part.rb

class Part < ActiveRecord::Base
  before_validation :strip_whitespace

protected
  def strip_whitespace
    self.title = self.title.strip
  end
end

规格/模型/ part_spec.rb

require 'spec_helper'

describe Part do
  it "should remove extra space when validated" do
    part = Part.new(:title => " Test")
    part.valid?
    part.title.should == "Test"
  end
end

这将在包含验证时通过,并在验证被注释掉时失败。

答案 1 :(得分:4)

参考@danivovich例子

class Part < ActiveRecord::Base
  before_validation :strip_whitespace

protected
  def strip_whitespace
    self.title = self.title.strip
  end
end

编写规范的正确方法是分别在 strip_whitespace 方法上编写规范,然后检查模型类是否设置了回调,如下所示:。

describe Part do
  let(:record){ described_class.new }

  it{ described_class._validation_callbacks.select{|cb| cb.kind.eql?(:before)}.collect(&:filter).should include(:strip_whitespace) }

  #private methods
  describe :strip_whitespace do
    subject{ record.send(:strip_whitespace)} # I'm using send() because calling private method
    before{  record.stub(:title).and_return('    foo    ')
    it "should strip white spaces" do
      subject.should eq 'foo'
      # or even shorter
      should eq 'foo'
    end
  end
end

如果您需要在某些情况下跳过回调行为,请使用

before{ Part.skip_callback(:validation, :before, :strip_whitespace)}
before{ Part.set_callback( :validation, :before, :strip_whitespace)}

2013年1月20日更新

BTW我用RSpec匹配器编写了一个gem来测试这个https://github.com/equivalent/shoulda-matchers-callbacks

一般情况下,我不建议回拨。例如,在这个问题中它们很好,但是一旦你做了更复杂的事情,比如:

创建后 - >

  • 将帐户关联到用户
  • 创建通知
  • 向管理员发送电子邮件

...然后你应该创建自定义服务对象来处理它并单独测试它们。