模拟补丁模块
Mocking a patch module
我有一个代码库,它在两种情况下进行了测试:运行 通过入口点 A 和 B。当它是通过 A 的 运行 时,数据库连接按原样使用。当它是 运行 通过 B 时,ActiveRecord::Base.connection
是猴子补丁。
由于 B 只是一个辅助脚本,目前在 rspec 中通过 运行 将其作为外部命令测试并检查输出。不过,我想恢复理智并测试行为而不产生新进程。
有没有办法在 rspec mocks 到 "temporarily extend" a class?我想获得以下行为:
before do
ActiveRecord::Base.connection.extend(App::SomePatch)
end
after do
ActiveRecord::Base.connection.unextend(App::SomePatch)
end
unextend当然不存在。我只有 3 个方法需要修补,所以我可以为每个方法使用模拟,但是方法别名使这变得复杂。
补丁模块如下所示:
module SomePatch
def SomePatch.included(mod)
alias :old_execute :execute
end
def execute(*args) ... end
def some_storage
@some_storage ||= []
end
end
我会选择克隆,大致如下:
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
我没有测试过,但只要没有 "quirks" 克隆对象,这应该没问题。
编辑:好的,这行不通,因为没有 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
因为模拟将是 "undone"
我有一个代码库,它在两种情况下进行了测试:运行 通过入口点 A 和 B。当它是通过 A 的 运行 时,数据库连接按原样使用。当它是 运行 通过 B 时,ActiveRecord::Base.connection
是猴子补丁。
由于 B 只是一个辅助脚本,目前在 rspec 中通过 运行 将其作为外部命令测试并检查输出。不过,我想恢复理智并测试行为而不产生新进程。
有没有办法在 rspec mocks 到 "temporarily extend" a class?我想获得以下行为:
before do
ActiveRecord::Base.connection.extend(App::SomePatch)
end
after do
ActiveRecord::Base.connection.unextend(App::SomePatch)
end
unextend当然不存在。我只有 3 个方法需要修补,所以我可以为每个方法使用模拟,但是方法别名使这变得复杂。
补丁模块如下所示:
module SomePatch
def SomePatch.included(mod)
alias :old_execute :execute
end
def execute(*args) ... end
def some_storage
@some_storage ||= []
end
end
我会选择克隆,大致如下:
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
我没有测试过,但只要没有 "quirks" 克隆对象,这应该没问题。
编辑:好的,这行不通,因为没有 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
因为模拟将是 "undone"