Rspec2 тестирование метода before_validation - PullRequest
7 голосов
/ 09 сентября 2011

У меня есть следующее, чтобы удалить пробелы в определенном атрибуте.

#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 ]

14 голосов
/ 09 сентября 2011

Проверки не будут выполняться до тех пор, пока объект не будет сохранен или вы не вызовете valid? вручную.Ваш before_validation обратный вызов не выполняется в вашем текущем примере, потому что ваши проверки никогда не проверяются.В вашем тесте я бы предложил, чтобы вы запустили @part.valid? перед проверкой того, что заголовок изменен на ожидаемый.

app / models / part.rb

class Part < ActiveRecord::Base
  before_validation :strip_whitespace

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

spec/models/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

Это пройдет, когда проверка включена, и завершится неудачей, когда проверка закомментирована.

4 голосов
/ 11 сентября 2012

со ссылкой на пример @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)}

Обновление от 20.01.2013

Кстати, я написал гем с помощью RSpec matchers, чтобы проверить это https://github.com/equivalent/shoulda-matchers-callbacks

В общем, я вообще не рекомендую обратный вызов. Они хороши, например, в этом вопросе, однако, как только вы сделаете более сложные вещи, такие как:

После создания ->

  • ссылка на аккаунт пользователя
  • создать уведомление
  • отправить письмо администратору

... тогда вам нужно создать объект пользовательской службы, чтобы разобраться с этим и протестировать их отдельно.

...