我可以使用 rspec 模拟来消除版本常量吗?

发布于 2024-08-10 10:26:04 字数 174 浏览 5 评论 0原文

我的代码只需要在特定版本的 ActiveRecord 上运行(旧 AR 库上的错误的解决方法)。此代码测试 ActiveRecord::VERSION 常量的值以查看是否需要运行。

有没有办法在 rspec 中模拟这些常量,以便我可以测试该代码路径,而无需依赖在测试机器上安装正确的 ActiveRecord gem?

I've got code that only needs to run on a certain version of ActiveRecord (a workaround for a bug on old AR libraries). This code tests the values of ActiveRecord::VERSION constants to see if it needs to be run.

Is there a way to mock out those constants in rspec so I can test that code path without relying on having the right ActiveRecord gem installed on the test machine?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

酷遇一生 2024-08-17 10:26:04

我最终编写了一个帮助器方法,让我在执行代码块时覆盖常量:

def with_constants(constants, &block)
  constants.each do |constant, val|
    Object.const_set(constant, val)
  end

  block.call

  constants.each do |constant, val|
    Object.send(:remove_const, constant)
  end
end

将此代码放入您的 spec_helper.rb 文件后,可以按如下方式使用它:

with_constants :RAILS_ROOT => "bar", :RAILS_ENV => "test" do
  code goes here ...
end

希望这对您有用。

I ended up writing a helper method to let me override constants while executing a block of code:

def with_constants(constants, &block)
  constants.each do |constant, val|
    Object.const_set(constant, val)
  end

  block.call

  constants.each do |constant, val|
    Object.send(:remove_const, constant)
  end
end

After putting this code in your spec_helper.rb file, it can be used as follows:

with_constants :RAILS_ROOT => "bar", :RAILS_ENV => "test" do
  code goes here ...
end

Hope this works for you.

战皆罪 2024-08-17 10:26:04

在 RSpec 2.11 中,stub_const 支持开箱即用的常量存根:

describe "stub_const" do
  it "changes the constant value for the duration of the example" do
    stub_const("Foo::SIZE", 10)
    expect(Foo::SIZE).to eq(10)
  end
end

有关更多详细信息,请参阅 Myron Marston 的公告:

With RSpec 2.11, constant stubbing is supported out of the box with stub_const:

describe "stub_const" do
  it "changes the constant value for the duration of the example" do
    stub_const("Foo::SIZE", 10)
    expect(Foo::SIZE).to eq(10)
  end
end

See Myron Marston's announcement for more details:

睡美人的小仙女 2024-08-17 10:26:04

德鲁·奥尔森(Drew Olson),我采纳了你的想法并做了一些修改以添加范围:

class Object
  def self.with_constants(constants, &block)
    old_constants = Hash.new
    constants.each do |constant, val|
      old_constants[constant] = const_get(constant)
      silence_stderr{ const_set(constant, val) }
    end

    block.call

    old_constants.each do |constant, val|
      silence_stderr{ const_set(constant, val) }
    end
  end
end

将此代码放入 specs/support/with_constants.rb 文件后,可以按如下方式使用:

MyModel.with_constants :MAX_RESULT => 2, :MIN_RESULT => 1 do
  code goes here ...
end

Drew Olson, I took your idea and made a few modifications to add scoping:

class Object
  def self.with_constants(constants, &block)
    old_constants = Hash.new
    constants.each do |constant, val|
      old_constants[constant] = const_get(constant)
      silence_stderr{ const_set(constant, val) }
    end

    block.call

    old_constants.each do |constant, val|
      silence_stderr{ const_set(constant, val) }
    end
  end
end

After putting this code at specs/support/with_constants.rb file, it can be used as follows:

MyModel.with_constants :MAX_RESULT => 2, :MIN_RESULT => 1 do
  code goes here ...
end
岁月染过的梦 2024-08-17 10:26:04

添加救援块对于确保测试套件中其他测试的恢复恒定非常重要!

class Object
  class << self
    def with_constants(constants, &block)
      old_constants = Hash.new
      constants.each do |constant, val|
        old_constants[constant] = const_get(constant)
        Kernel::silence_warnings { const_set(constant, val) }
      end

      error = nil
      begin
        block.call
      rescue Exception => e
        error = e
      end

      old_constants.each do |constant, val|
        Kernel::silence_warnings { const_set(constant, val) }
      end

      raise error unless error.nil?
    end
  end
end

通常

describe "#fail" do

  it "should throw error" do
    expect {
      MyModel.with_constants(:MAX_RESULT => 1) do
        # code with throw error
      end
    }.to raise_error
  end

end 

Add rescue block is important for ensure restore constant for another tests in test suite !

class Object
  class << self
    def with_constants(constants, &block)
      old_constants = Hash.new
      constants.each do |constant, val|
        old_constants[constant] = const_get(constant)
        Kernel::silence_warnings { const_set(constant, val) }
      end

      error = nil
      begin
        block.call
      rescue Exception => e
        error = e
      end

      old_constants.each do |constant, val|
        Kernel::silence_warnings { const_set(constant, val) }
      end

      raise error unless error.nil?
    end
  end
end

Typically

describe "#fail" do

  it "should throw error" do
    expect {
      MyModel.with_constants(:MAX_RESULT => 1) do
        # code with throw error
      end
    }.to raise_error
  end

end 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文