以下规范有效,但我知道它不应该是这样的。我很难了解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的良好资源,请添加一些链接。
由于
答案 0 :(得分:1)
我会在这里改变一些事情:
it
中的大部分代码只是提供上下文,因此应该在您的before(:each)块中。 stub
。另一个测试可能是it 'should call 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
一些测试资源: