Rails 3: ActiveRecord observer: after_commit callback doesn't fire during tests, but after_save does fire

南楼画角 提交于 2019-12-05 23:44:30

To properly execute database commits you need to enable config.use_transactional_fixtures, but I'd recommend you consider different strategies as that option is disabled by default for the sake of good test design, to enforce your tests to be as unitary and isolated as possible.

First, you can run ActiveRecord callbacks with #run_callbacks(type), in your case model.run_callbacks(:commit)

My preferred strategy is to have a method with the logic you want to run, then declare the hook using the method name, then test the method behavior by calling it directly and test that the method is called when the hook is run.

class Person
  after_commit :register_birth

  def register_birth
    # your code
  end
end

describe Person do
  describe "registering birth" do
    it "registers ..." do
    end

    it "runs after database insertion" do
      expect(model).to receive(:register_birth)
      model.run_callbacks(:commit)
    end
  end
end

That assumes that whatever logic you have on the callback is not essential for the model state, i.e. doesn't change it to something you need to consume right away, and that any other model that interacts with it is indifferent to it. And as such isn't required to run in a test context. That is a powerful design principle that in the long term prevents callbacks to get out of control and generate dependencies for tests by demanding some property unrelated to the unit you are testing to be setup only to be consumed on a callback that you don't care about at that moment.

But, in the end you know your domain and design requirements better than a stranger so, if you really need the after_commit to run, you can force it with model.run_callbacks(:commit). Just encapsulate that on your factory/fixture and you don't have to remember it every time.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!