如何在规范中创建类而不污染全局命名空间?



在规范的上下文中定义类并且不让它污染全局命名空间的最佳方法是什么?另一个文件如何访问该常量?

bowling_spec.rb

require "spec_helper"
describe Bowling do
context "when validate is defined" do
let(:dummy_class) {
Class.new(described_class) do
METRICS_NAMESPACE = "ExtendedClass.Metrics.namespace"
end
}
it "does nothing" do
dummy_class 
end
end
end

规格 - batting_spec.rb

require "spec_helper"
describe Batting do
context do
it "does weird thing" do
expect { self.class.const_get(:METRICS_NAMESPACE) }.to raise_error(NameError)
end
end
end

如果运行单个等级库文件

rspec spec/batting_spec.rb
.
Finished in 0.00285 seconds (files took 0.12198 seconds to load)
1 example, 0 failures

如果您运行定义虚拟类的规范

rspec spec/bowling_spec.rb spec/batting_spec.rb
.F
Failures:
1) Batting  does weird thing
Failure/Error: expect { self.class.const_get(:METRICS_NAMESPACE) }.to raise_error(NameError)
expected NameError but nothing was raised
# ./spec/batting_spec.rb:6:in `block (3 levels) in <top (required)>'
Finished in 0.01445 seconds (files took 0.12715 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/batting_spec.rb:5 # Batting  does weird thing

重现错误:我创建了一个存储库:https://github.com/pratik60/rspec-pollution 更新的自述文件

> 运行rspec spec/batting_spec.rb spec/bowling_spec.rb

2 examples, 0 failures

跑步rspec spec/bowling_spec.rb spec/batting_spec.rb给出您提到的错误。

使用 binding.pry:

describe Batting do
context do
it "does weird thing" do
require 'pry'
binding.pry
expect { self.class.const_get(:METRICS_NAMESPACE) }.to raise_error(NameError)
end
end
end

自我.class祖先

[RSpec::ExampleGroups::Batting::Anonymous,
RSpec::ExampleGroups::Batting::Anonymous::LetDefinitions,
RSpec::ExampleGroups::Batting::Anonymous::NamedSubjectPreventSuper,
RSpec::ExampleGroups::Batting,
RSpec::ExampleGroups::Batting::LetDefinitions,
RSpec::ExampleGroups::Batting::NamedSubjectPreventSuper,
RSpec::Core::ExampleGroup,

沿着继承树向下走

RSpec::Core::ExampleGroup::METRICS_NAMESPACE
(pry):4: warning: toplevel constant METRICS_NAMESPACE referenced by RSpec::Core::ExampleGroup::METRICS_NAMESPACE
=> "ExtendedClass.Metrics.namespace"

检查链上的第一个对象

Object::METRICS_NAMESPACE

=>"ExtendedClass.Metrics.namespace"

甚至更远

Class::METRICS_NAMESPACE
(pry):2: warning: toplevel constant METRICS_NAMESPACE referenced by Class::METRICS_NAMESPACE
=> "ExtendedClass.Metrics.namespace"

TL ;博士

正如您所说,当您执行METRICS_NAMESPACE = "ExtendedClass.Metrics.namespace"时,您创建了一个全局命名空间常量。(即,最上面的红宝石常量 Class 中的常量(

只需执行此操作即可

Class.new(described_class) do
self.const_set('METRICS_NAMESPACE', "ExtendedClass.Metrics.namespace")
end

rspec spec/bowling_spec.rb spec/batting_spec.rb

Finished in 1.55 seconds (files took 0.08012 seconds to load)
2 examples, 0 failures

最新更新