首页 > 解决方案 > 如何在 Rspec 测试中允许对模块常量的非限定访问?

问题描述

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

这个问题正在寻找一种方法来允许从 rspec 3.9 示例中的模块中无限制地引用常量。这主要是为了节省空间和打字。

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不选择常量。

这是从 module中包含辅助函数的一种方便方法,但它与在类上使用 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不起作用。

从先前关闭的 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

复制所有常量是行不通的

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

标签: rubyrspec

解决方案


一种方法是在模块的上下文中定义 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

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


推荐阅读