更改 rspec 中关联对象的正确方法

ggo*_*oha 5 ruby rspec ruby-on-rails let factory-bot

我最近开始使用 rspec 进行测试,所以我可能会犯错误,如果有更好的方法请纠正我

我创建了两个相关模型

let(:user) {FactoryGirl.create :user} 
let!(:participation) {FactoryGirl.create :participation, user: user}
Run Code Online (Sandbox Code Playgroud)

在其中一项测试更改相关对象之一之前

context "when" do
  before {participation.prize = 100}
  it "" do
    binding.pry
  end
end
Run Code Online (Sandbox Code Playgroud)

但里面

participation.prize => 100
user.participatons.select(:prize) => nil
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么 ?以及如何解决它?

Gly*_*oko 3

当您说 时user.participations.select(:prize),您正在向数据库进行查询以获取用户参与奖品列中的值。但是当你说before {participation.prize = 100}你只是在参与对象上设置奖品属性时。尝试在选择行之前保存参与:

participation.prize # => 100
participation.save
user.participatons.select(:prize) # => nil
Run Code Online (Sandbox Code Playgroud)

另一个可能的问题是user.participations先前的调用已记住该问题。确保这件事user.participations.first == participation。如果没有,请检查

1)puts participation.user_id

2)puts user.participations, user.reload.participations


最后,设置测试以便减少遇到此问题的更好方法是:

# let(:price) { 0 } # default price. Optional so that tests won't throw errors if you forget to set it in a context/describe block.
let(:user) {FactoryGirl.create :user} 
let!(:participation) {FactoryGirl.create :participation, user: user, price: price}

# ...

context "when ..." do
  let(:price) { 100 }
  it "" do
    binding.pry
  end
end
Run Code Online (Sandbox Code Playgroud)

这样,价格就会在您创建模型时设定。遵循这种模式通常意味着更少遇到这个问题。