包含被测模块时使用describe_class

Lei*_*eif 5 ruby rspec

我正在编写一些rspec来测试某些模块正确实现其行为。

该模块如下所示:

module Under::Test
  def some_behaviour
  end
end
Run Code Online (Sandbox Code Playgroud)

我不能在RSpec中做到这一点:

describe Under::Test do
  subject {Class.new{include described_class}.new}
Run Code Online (Sandbox Code Playgroud)

#described_class被调用时,由于self是Class的实例,没有#describe_class方法,因此无法再解决它。所以我不得不重复自己:

subject {Class.new{include Under::Test}.new}
Run Code Online (Sandbox Code Playgroud)

或以与客户使用方式不同的方式在规范中使用它:

subject {Object.new.extend described_class}
Run Code Online (Sandbox Code Playgroud)

这具有相同的最终效果,但是我内心深处认为,如果我要我的客户要求include Under::Test,那么测试应该看起来尽可能地接近他们使用它们的方式。

我可以使用闭包属性来解决此问题,但我想知道这是否更好。这有代码气味吗?

describe Under::Test do
  subject {mudule = described_class;Class.new{include mudule}.new}

  it 'has some behaviour' do
    expect(subject.some_behaviour).to be
  end
end
Run Code Online (Sandbox Code Playgroud)

注意,我在r / ruby​​上的reddit上也问过,有人建议:

subject {Class.new.include(described_class).new}
Run Code Online (Sandbox Code Playgroud)

这可能就是我的去向。

SHS*_*SHS 5

如果最终目标是新创建include的当前described_class模块Class,那么以下解决方法如何?

RSpec.describe NewModule do
  let(:test_class) do
    Class.new.tap do |klass|
      klass.include(described_class)
    end
  end

  specify do
    expect(test_class.ancestors).to include described_class # passes
  end
end
Run Code Online (Sandbox Code Playgroud)

这是在对象中包含模块方法的示例:

module NewModule
  def identity
    itself
  end
end

RSpec.describe NewModule do
  let(:one) do
    1.tap do |obj|
      obj.class.include(described_class)
    end
  end

  specify do
    expect(one.identity).to eq 1 # passes
  end
end
Run Code Online (Sandbox Code Playgroud)

请注意,Ruby v2 +中没有includea 的方法。如果您使用的是旧版本,则必须使用Classprivateklass_name.send(:include, described_class)