Rspec2 тестирует метод before_validation

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

#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

Что мне не хватает?


person Kleber S.    schedule 09.09.2011    source источник


Ответы (2)


Проверка не будет выполняться до тех пор, пока объект не будет сохранен или пока вы не вызовете 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

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

person danivovich    schedule 09.09.2011
comment
Тест проходит, даже если я прокомментирую строку before_validation. - person Kleber S.; 09.09.2011
comment
Я добавил код из быстрого теста, который я собрал вместе, и он работает, как и ожидалось. Если у вас все еще есть проблемы, в вашем приложении должно быть что-то отличающееся, поэтому нам может потребоваться увидеть больше вашего кода, чтобы помочь в дальнейшем. - person danivovich; 09.09.2011
comment
Кажется, что .eql?("Test") ведет себя иначе, чем == "Test". Изменив это, тест работает так, как ожидалось. Спасибо @danivovich! - person Kleber S.; 09.09.2011
comment
Очень интересно. Внимательный взгляд на документы rspec показывает, что should.eql? не является ожидаемым использованием проверки равенства, используйте либо ==, либо eq(..). Я думаю, что ваша строка просто оценивала, что Test не совпадает с сопоставителем, но ничего не утверждала. relishapp.com/rspec/rspec-expectations/docs/ встроенные сопоставители/ - person danivovich; 09.09.2011

ссылаясь на пример @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 января 2013 г.

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

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

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

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

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

person equivalent8    schedule 11.09.2012