Ожидание изменения rspec не выполняется при использовании активной пессимистической блокировки записи

У меня есть 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?

1 ответ

Решение

Ваша проблема в том, что экземпляр foo.parent в вашем тесте RSpec это не тот же экземпляр parent что твой Foo#bump! метод модифицируется, потому что вызов parent.lock! перезагружает родительскую ассоциацию, чтобы получить блокировку, и, таким образом, вы изменяете экземпляр, отличный от rspec, к которому привязана его собственная лямбда. Самое простое решение - использовать change { } синтаксис, который не привязывает экземпляр получателя к foo.parent но вместо этого просто foo, который не меняется, вот так:

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

Это исправление работало локально для меня.

Другие вопросы по тегам