模拟补丁模块

时间:2018-05-23 09:41:39

标签: ruby rspec monkeypatching

我有一个代码库,它在两种情况下进行测试:通过入口点A和B运行。当它通过A运行时,db连接按原样使用。当它通过B运行时,ActiveRecord::Base.connection被猴子修补。

由于B只是一个帮助脚本,因此它目前在rspec中通过将其作为外部命令运行并检查输出来进行测试。我想带回一些理智并测试行为,但不会产生新的过程。

在rspec模拟中有没有办法“暂时扩展”一个类?我想得到做的行为:

before do
  ActiveRecord::Base.connection.extend(App::SomePatch)
end
after do
  ActiveRecord::Base.connection.unextend(App::SomePatch)
end

当然,不存在不存在。我只有3种方法可以修补,所以我可能会为每种方法使用模拟,但方法别名会使这变得复杂。

补丁模块如下所示:

module SomePatch
  def SomePatch.included(mod)
    alias :old_execute :execute
  end

  def execute(*args) ... end

  def some_storage
    @some_storage ||= []
  end
end

1 个答案:

答案 0 :(得分:1)

我会选择克隆,就像这样:

before do
  @original_connection = ActiveRecord::Base.connection
  ActiveRecord::Base.connection = @original_commention.dup
  ActiveRecord::Base.connection.extend(App::SomePatch)
end

after do
  ActiveRecord::Base.connection = @original_connection
end

我没有测试过,但是只要克隆对象没有“怪癖”,这应该没问题。

编辑:好的,这不起作用,因为没有connection=方法,所以你可以尝试使用模拟:

before do
  @original_connection = ActiveRecord::Base.connection
  new_connection = @original_connection.dup
  new_connection.extend(App::SomePatch)
  allow(ActiveRecord::Base).to receive(:connection).and_return(new_connection)
end

你可能不需要after,因为模拟将是“撤消”