0

我有一种Rails 4.2.0使用悲观锁定来更改计数器的方法

class Foo < < ActiveRecord::Base
  def bump!
    transaction do
      lock!
      parent.lock!

      lock.counter += 1
      parent.counter += 1

      save!
      parent.save!
    end
  end
end

我用Rspec 3.1这样的方式测试它

expect{foo.bump!}.to change(foo, :counter).by(1)
expect{foo.bump!}.to change(foo.parent, :counter).by(1)

第一个change(foo, :counter)测试通过,但第二个change(foo.parent, :counter)失败,除非我同时注释掉lock!parent.lock!

如果我像这样重写失败的测试,它会通过

prev_counter = foo.parent.counter
foo.bump!
expect(foo.parent.counter).to eq prev_counter + 1

为什么它不起作用expect{...}.to change

4

1 回答 1

1

您的问题是foo.parent您的 RSpec 测试中的实例与parent您的Foo#bump!方法正在修改的实例不同,因为调用parent.lock! 会重新加载父关联以获取锁,因此您修改的实例与rspec 将其自己的 lambda 绑定到. 最简单的解决方法是使用不将接收器实例绑定到而是仅change { }绑定到的语法,它不会改变,如下所示:foo.parentfoo

expect{foo.bump!}.to change{foo.counter}.by(1)
expect{foo.bump!}.to change{foo.parent.counter}.by(1)

此修复程序在本地对我有用。

于 2015-07-27T21:39:16.810 回答