【问题标题】:How to create classes in specs without polluting global namespace?如何在规范中创建类而不污染全局命名空间?
【发布时间】:2020-06-02 20:11:22
【问题描述】:

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

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

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

【问题讨论】:

    标签: ruby-on-rails ruby testing rspec


    【解决方案1】:

    运行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
    

    self.class.ancestors

    [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" 时,您创建了一个全局命名空间常量。 (即最上面的 ruby​​ 常量 Class 中的一个常量)

    只需这样做

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

    rspec 规格/bowling_spec.rb 规格/batting_spec.rb

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

    【讨论】:

      猜你喜欢
      • 2014-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 2017-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多