Как я должен специфицировать это - PullRequest
1 голос
/ 02 октября 2009

Следующая спецификация работает, но я знаю, что так не должно быть. Мне трудно разобраться в rspec, в частности, издеваться и заглушки.

Это код модели

class RecipeFermentable < ActiveRecord::Base
  belongs_to :recipe
  belongs_to :product

  def set_attributes()
    attrs = product.product_attributes
    self.ppg = attrs.find_by_name(:ppg.to_s).value
    self.ecb = attrs.find_by_name(:ecb.to_s).value
  end
end

И это спецификация, которую я написал

  it "should set the attributes from the product" do
    @product_attribute1 = mock_model(ProductAttribute, :name => :ppg, :value => 40)
    @product_attribute2 = mock_model(ProductAttribute, :name => :ecb, :value => 1)

    @product = Product.new
    @product.product_attributes << @product_attribute1
    @product.product_attributes << @product_attribute2
    @recipe_fermentable = RecipeFermentable.new
    @recipe_fermentable.product.should_receive(:product_attributes).and_return(@product_attributes)
    @product_attributes.stub(:find_by_name).with(:ppg.to_s).and_return(@product_attribute1)
    @product_attributes.stub(:find_by_name).with(:ecb.to_s).and_return(@product_attribute2)

    @recipe_fermentable.set_attributes

    @recipe_fermentable.ppg.should eql(40)
    @recipe_fermentable.ecb.should eql(1)
 end

Для начала, моя спецификация намного больше, чем мой метод, и я использую настоящий Продукт. Некоторые советы по написанию хорошей спецификации для этого были бы очень полезны. Также, если кто-нибудь знает хороший ресурс для изучения rspec с использованием макетов и заглушек, пожалуйста, не могли бы вы добавить несколько ссылок.

Спасибо

1 Ответ

1 голос
/ 02 октября 2009

Я бы изменил пару вещей здесь:

  • Большая часть кода в it просто предоставляет контекст, поэтому он должен находиться в вашем блоке before (: each).
  • Вы устанавливаете ожидание сообщения, но не похоже, что вы проверяете это. Я думаю, что ожидание должно быть переключено на stub вместо этого. Другим тестом может быть it 'should call product_attributes', где вы на самом деле протестируете это ожидание - я не рекомендую вам делать это, поскольку вы будете тестировать реализацию, а не поведение, а просто высказывать свое мнение.
  • Вы возвращаете @product_attributes в ожидании этого сообщения и используете его сразу после того, как заглушите вызовы find_by_name. Однако вы никогда не определяли @product_attributes. Я предполагаю, что это должен быть фиктивный объект, и я не уверен, что это действительно в этом контексте. Может быть, это ноль, и вы используете несколько методов.

С этими двумя изменениями мы находимся здесь:

before(:each) do
  @product                = mock_model(Product)
  @product_attribute_ppg  = mock_model(ProductAttribute, :name => :ppg, :value => 40)
  @product_attribute_ecb  = mock_model(ProductAttribute, :name => :ecb, :value => 1)
  @product_attributes     = mock('product_attributes')
  @product_attributes.stub!(:find_by_name).with(:ppg.to_s).and_return(@product_attribute_ppg)
  @product_attributes.stub!(:find_by_name).with(:ecb.to_s).and_return(@product_attribute_ecb)
  @product.stub!(:product_attributes).and_return(@product_attributes)

  @recipe_fermentable = RecipeFermentable.new
  @recipe_fermentable.stub!(:product).and_return(@product)
end

it 'should set the attributes from the product' do
  @recipe_fermentable.set_attributes
  @recipe_fermentable.ppg.should eql(40)
  @recipe_fermentable.ecb.should eql(1)
end

Учитывая все это, я не совсем согласен с вашим подходом здесь. Я думаю, что вы повторяете данные и уходите от нормализации БД. Если только для этого нет реальной причины (может быть, ваш путь вперед и по причинам производительности вы должны были это сделать), я бы предложил следующее:

class RecipeFermentable < ActiveRecord::Base
  def ppg
    #rescue nil here so that if attributes is nil, or find_by_name('ppg') is nil, things don't blow up
    product.attributes.find_by_name('ppg').value rescue nil
  end

  #other
end

Пара ресурсов для тестирования:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...