【问题标题】:Testing models with relationships and callbacks in Rails with RSpec and Factory_Girl使用 RSpec 和 Factory_Girl 在 Rails 中测试具有关系和回调的模型
【发布时间】:2010-07-01 20:00:19
【问题描述】:

我仍在努力学习 RSpec,所以如果完全忽略了某些内容,我很抱歉......

我正在为包含多种成分的食谱编写测试。成分实际上是以百分比形式添加的(配方中有一个总百分比列),所以我想确保每次保存后总列都会更新。

所以现在我对 recipe_ingredient 模型的 RSpec 测试是这样的:

it "should update recipe total percent" do
  @recipe = Factory.create(:basic_recipe)

  @ingredient.attributes = @valid_attributes.except(:recipe_id)
  @ingredient.recipe_id = @recipe.id
  @ingredient.percentage = 20
  @ingredient.save!

  @recipe.total_percentage.should == 20
end

我有一个 after_save 方法,它只调用刚刚保存的收据成分的快速更新。这很简单:

编辑:此 update_percentage 操作在配方模型中。我保存成分后调用的方法只是查找它的配方,然后在其上调用此方法。

def update_percentage    
  self.update_attribute(:recipe.total_percentage, self.ingredients.calculate(:sum, :percentage))
end

我是不是搞砸了?运行测试时我无权访问父对象吗?我尝试运行一种基本方法来在保存后更改父配方名称,但这不起作用。我确定这是我忽略的关系中的某些东西,但所有关系都设置正确。

感谢您的任何帮助/建议!

【问题讨论】:

    标签: ruby-on-rails ruby rspec factory-bot


    【解决方案1】:

    update_attribute 用于更新当前对象的属性。这意味着您需要在要更新其属性的对象上调用update_attribute。在这种情况下,您要更新配方,而不是成分。所以你必须打电话给recipe.update_attribute(:total_percentage, ...)

    此外,成分属于食谱,而不是其他成分。所以你应该打电话给recipe.ingredients.sum(:percentage),而不是self.ingredients.sum(:percentage)

    另外,您需要重新加载 @recipe,然后才能测试它的 total_percentage。尽管它与@ingredient.recipe 引用相同的数据库记录,但它并没有指向内存中的同一个Ruby 对象,因此对一个对象的更新不会出现在另一个对象中。保存@ingredient 后重新加载@recipe 以从数据库中获取最新值。

    【讨论】:

    • 抱歉,update_percentage 方法在配方模型中存在混淆。成分的 after_save 方法会加载配方 (@recipe = Recipe.find(self.recipe_id)),然后对其调用 update_percentage (@recipe.update_percentage) 如何在测试中重新加载配方?
    • 在测试中尝试了“@recipe.reload”,它成功了。谢谢伊恩,没想到我必须这样做!
    【解决方案2】:

    顺便说一句,您可以以更清晰的方式构建您的成分,因为您已经在使用 factory_girl:

    @ingredient = Factory(:ingredient, :recipe => @recipe, :percentage => 20)
    

    这将构建并保存一个成分。

    【讨论】:

      【解决方案3】:

      嘿,或者你在检查配方上的总百分比之前放置一个@recipe.reload,或者使用期望。

       it "should update recipe total percent" do
        @recipe = Factory.create(:basic_recipe)
        expect {
         @ingredient.attributes = @valid_attributes.except(:recipe_id)
         @ingredient.recipe_id = @recipe.id
         @ingredient.percentage = 20
         @ingredient.save!
        }.to change(@recipe,:total_percentage).to(20)
      end
      

      我建议您看看这个演示文稿。关于 rspec 上新的和很酷的东西的许多提示。 http://www.slideshare.net/gsterndale/straight-up-rspec

      expect 是 lambda{}.should 的别名,您可以在此处阅读更多相关信息:rspec.rubyforge.org/rspec/1.3.0/classes/Spec/Matchers.html#M000168

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-01
        • 2012-01-23
        相关资源
        最近更新 更多