代码之家  ›  专栏  ›  技术社区  ›  viraptor

模拟补丁模块

  •  0
  • viraptor  · 技术社区  · 6 年前

    我有一个代码库,它在两个场景中进行了测试:通过入口点A和B运行。当它通过A运行时,DB连接按原样使用。当它通过B运行时, ActiveRecord::Base.connection 是猴子的补丁。

    由于b只是一个助手脚本,所以它目前在rspec中通过作为外部命令运行并检查输出来进行测试。不过,我想恢复理智,在不产生新过程的情况下测试行为。

    在rspec mocks中有没有一种方法可以“临时扩展”一个类?我想了解一下这种行为:

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

    当然,unextend不存在。我只有3个方法要修补,所以我可以对每个方法使用mock,但是方法别名会使这变得复杂。

    补丁模块如下所示:

    module SomePatch
      def SomePatch.included(mod)
        alias :old_execute :execute
      end
    
      def execute(*args) ... end
    
      def some_storage
        @some_storage ||= []
      end
    end
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Greg    6 年前

    我会去克隆,这条线的一些东西:

    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 因为模拟会被“撤销”