期待{subject}。改变(...)。by(1)不起作用

时间:2015-04-24 13:32:21

标签: ruby-on-rails rspec

此测试通过:

it 'test' do
  old = parenthood.student.balance
  Payment.money_transfer_to_child current_user: parenthood.user,
                                  student_id: parenthood.student.id,
                                  amount: '1',
                                  comment: 'some comment'
  expect(parenthood.student.reload.balance).to eq(old+1)
end

将其更改为以下形式使其无法通过("被0和#34更改):

subject { Payment.money_transfer_to_child current_user: parenthood.user,
                                              student_id: parenthood.student.id,
                                              amount: '1',
                                              comment: 'some comment' }
it { expect{ subject }.to change(parenthood.student.reload, :balance).by(1) }

我做错了什么?

2 个答案:

答案 0 :(得分:2)

我知道你找到了一种方法让它发挥作用,但也许让我们在这里有一个正确的答案。首先,为什么它不起作用。

it { expect{ subject }.to change(parenthood.student.reload, :balance).by(1) }

当执行此行时,所做的是(不完全但粗略地):

  1. 首先计算改变方法的参数。这意味着在此时评估parenthood.student.reload
  2. 在已评估的对象上调用balance方法,并记住该值。
  3. 执行期望的块(在这种情况下只是主题)
  4. 再次在对象上调用balance方法
  5. 此处的问题是parenthood.student.reload在执行subject之前已经过评估。执行subject之后,它再也没有计算过,因为它已经传递给了更改方法。这就是你在那里拥有旧价值的原因。

    你可以做的是要么有你的解决方案(但它不是很优雅,因为重新加载父母不是你正在测试的一部分)。或者您可以在更改匹配器中使用块并执行以下操作:

    it { expect{ subject }.to change { parenthood.student.reload.balance }.by(1) }
    

    该语法在运行parenthood.student.reload.balance之前和之后评估了subject的块,并且应该修复您的测试。

答案 1 :(得分:0)

在主题上添加一行解决了我的问题:

subject { Payment.money_transfer_to_child current_user: parenthood.user,
                                              student_id: parenthood.student.id,
                                              amount: '1',
                                              comment: 'some comment'
              parenthood.student.reload }