如何在 Rspec 测试中允许对模块常量的非限定访问?

How to permit unqualified access to constants of a module in Rspec tests?

想要在 RSpec 个示例中包含来自模块的常量。

这个问题正在寻找一种方法来允许对 rspec 3.9 示例中的模块中的常量进行非限定引用。这主要是为了节省 space 和打字。

module MyConsts
  FOO = "foo"
end

RSpec.describe "Tests Module Constants" do
  it 'has unqualified access to constants.' do
    expect(FOO).to eq("foo") 
  end
end

无效的方法:

RSpec::Core::Configuration#include 不提取常量。

这是 include helper functions from module 的一种便捷方法,但它与在 class 上使用 include 不同,因为常量无法按预期使用。

module MyConsts
  FOO = "foo"
end

RSpec.configure do |c|
  c.include MyConsts
end

RSpec.describe "Tests Module Constants" do
  it 'has qualified access to constants.' do
    expect(MyConsts::FOO).to eq("foo")
  end

  it 'has unqualified access to constants.' do
    expect(FOO).to eq("foo") 
  end
end

非限定访问示例失败。能够混入模块中的常量就好了,这样的例子就可以通过了。

Failures:
  1) Tests Module Constants has unqualified access to constants.
     Failure/Error: expect(FOO).to eq("foo")

     NameError:
       uninitialized constant FOO

describe 块中使用 include 无效。

从之前的 closed issue of rspec 可以引导人们相信在 describe 块中使用 include 是可行的。它没有。

module MyConsts
  FOO = "foo"
end

RSpec.describe "Tests Module Constants" do
  include MyConsts

  it 'has unqualified access to constants.' do
    expect(FOO).to eq("foo") 
  end
end

复制所有常量是行不通的

这个answer to a very similar question suggests using a shared_context。虽然它确实产生了最终结果,但它需要复制常量定义。这是一个问题,因为它们有数百个,常量模块完全是从另一个项目中提取的,要使它们保持最新状态工作量太大。

一种方法是在模块上下文中定义 RSpec 测试:

module MyConsts
  FOO = "foo"
end

module MyConsts
  RSpec.describe "Tests Module Constants" do
    it "has unqualified access to constants." do
      expect(FOO).to eq("foo")
    end
  end
end

RSpec.describe 定义一个模块,如果它被定义为 MyConsts 的子项,那么常量查找将冒泡到 MyConsts。

您也可以在顶层混合使用 MyConsts:

include MyConsts

这种方法可能不太理想,因为它会使这些常量在 任何地方 都可用,从而使它们有效地全局化,这可能比您想要的更容易泄漏。