包含被测模块时使用describe_class

时间:2015-11-09 03:05:10

标签: ruby rspec

我正在写一些rspec来测试一些模块正确实现他们的行为。

该模块如下所示:

module Under::Test
  def some_behaviour
  end
end

我无法在RSpec中执行此操作:

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

在调用点#described_class时,它无法再被解析,因为self是Class的一个实例,它没有#describe_class方法。所以我不得不重复自己:

subject {Class.new{include Under::Test}.new}

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

subject {Object.new.extend described_class}

这具有相同的最终效果,但我认为如果我要求我的客户include Under::Test,那么测试应该看起来与它们如何使用它们一样接近可能的。

我可以使用closure属性来解决这个问题,但我想知道它是不是更好。这有代码味吗?

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

注意,我还在reddit的r / ruby​​中询问过,有人建议:

subject {Class.new.include(described_class).new}

这可能就是我的方式。

2 个答案:

答案 0 :(得分:5)

如果您的最终目标是deadline新创建的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

请注意,在Ruby v2 +中,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 的{​​{1}}方法不是include。如果您使用的是旧版本,则必须使用Class

答案 1 :(得分:2)

我认为你的解决方案都很好,我更喜欢

Object.new.extend described_class

因其可读性和简洁性。如果您想使用Class.new方法,我认为重复模块名称是可以的,正如Jared所说,可读性在这里比干燥更重要。