4

以下代码不起作用,但它最好地显示了我想要实现的目标

context "this context describes the class" do

  subject do
    # described class is actually a module here
    c = Class.new.extend(described_class)
    c.some_method_that_has_been_added_through_extension
    c
  end

  # ... testing the class itself here ...

  context "instances of this class" do

    subject do
      # this doesn't work because it introduces a endless recursion bug
      # which makes perfectly sense
      subject.new
    end

  end

end

我还尝试在使用主题初始化的内部上下文中使用局部变量,但没有运气。有什么方法可以从内部范围的主题定义中访问外部范围的主题?

4

3 回答 3

3

使用#subject 有时会引起麻烦。它“主要用于”与#its 等速记检查一起使用。

它还可以使示例更难阅读,因为它可以掩盖您测试的名称/意图。这是 David Chelimsky 写的一篇关于#subject 和 #let 主题及其在揭示意图中的作用的博客文章:http ://blog.davidchelimsky.net/blog/2012/05/13/spec-smell-explicit-use-主题/

尝试使用 let,而不是 https://www.relishapp.com/rspec/rspec-core/v/2-10/docs/helper-methods/let-and-let

这是我最有可能写它的方式。

context "this context describes the class" do
  let(:name_of_the_module) { Class.new.extend(described_class) }
  before do
    c.some_method_that_has_been_added_through_extension
  end

  # ... testing the class itself here ...

  context "instances of this class" do

    let(:better_name_that_describes_the_instance) { klass.new }

    # ... test the instance
  end

end

旁注 您可能想重新考虑是否要使用主题。我更喜欢在几乎所有情况下使用#let。YMMV

于 2012-05-26T12:05:35.057 回答
1

显然有效的方法是在内部上下文中使用实例变量,而不是用 the 初始化它。主题是 Procs。因此,我的第一种方法不起作用。subjectsubject.call

context "instances of this class" do

  klass = subject.call
  subject { klass.new }

end
于 2012-05-11T10:59:02.270 回答
0

我一直在寻找解决方案,但出于不同的原因。当我测试一个可能返回值或引发错误的方法时,我经常不得不在两个上下文中重复这个主题,一次是作为 proc,raise_error一次是正常的。

我发现你可以给出subjects名字,比如lets. 这让您可以subject在新的subject. 这是一个例子:

describe 'do_some_math' do
  let!(:calculator) { create(:calculator) }

  # proc to be used with raise_error
  subject(:do_some_math) { 
    -> { calculator.do_some_math(with, complicated, args) } 
  }

  context 'when something breaks' do
    it { is_expected.to raise_error } # ok
  end

  context 'when everything works' do

    # here we call the named subject from the outer scope:
    subject { do_some_math.call } # nice and DRY

    it { is_expected.to be_a(Numeric) } # also ok!
  end
end
于 2016-07-18T15:27:39.313 回答