RSPec:为正在测试的memoized类修复“警告:已初始化常量”

时间:2017-06-02 19:54:22

标签: ruby rspec

运行这个基本测试套件时,我一直看到这些警告:

spec/example_spec.rb:6: warning: already initialized constant DB_ID                                                  
spec/example_spec.rb:6: warning: previous definition of DB_ID was here
spec/example_spec.rb:8: warning: already initialized constant FIELDS
spec/example_spec.rb:8: warning: previous definition of FIELDS was here 

以下是一个示例测试:

require_relative 'spec_helper'

RSpec.describe MyModule::BaseClass do
  let(:example_class) do
    Class.new(described_class) do
      DB_ID = 'example'

      FIELDS = {
        a: 2,
        b: 4,
        c: 6
      }

      def foo
        'foo'
      end

      def bar
        'bar'
      end
    end
  end

  subject { example_class.new }

  it 'does foo' do
    expect(subject.foo).to eq('foo')
  end

  it 'does bar' do
    expect(subject.bar).to eq('bar')
  end
end

每次使用subject时都会触发警告。

我的理解是let定义了一个memoized辅助方法,以便example_class仅在第一次引用时评估一次。

如果这是真的,为什么我会收到这些警告?

1 个答案:

答案 0 :(得分:1)

  1. 当您使用Class.new时,您正在创建一个匿名(未命名)类。
  2. 当定义常量时,ruby需要解析为其定义常量的命名空间。
  3. 与模块或类不同,匿名类中的命名空间为空。

    class A
      p Module.nesting # => [A]
      B = 1
    end
    B    #=> NameError: uninitialized constant B
    A::B #=> 1
    
    Class.new(A) do
      p Module.nesting # => []
      C = 1
    end
    C #=> 1
    

    由于没有明确的命名空间将这些常量放在哪里,它们最终会被定义为"全局"在Object班。

    您可以使用以下示例自行尝试(使用--order defined运行):

    require_relative 'spec_helper'
    
    class Base
    end
    
    RSpec.describe Base do
      context 'creating an anonymous class with a constant' do
        let(:example_class) do
          Class.new(described_class) do
            DB_ID = 'example'
    
            def foo
              'foo'
            end
          end
        end
    
        it 'does foo' do
          expect(example_class.new.foo).to eq('foo')
        end
      end
    
      context 'the constant is on Object' do
        it 'does bar' do
          expect(DB_ID).to eq('example')
        end
      end
    end
    

    归结为红宝石常量查找的工作原理。这是一篇关于它的好文章https://cirw.in/blog/constant-lookup.html