【问题标题】:Does rspec memoize the `subject` block?rspec 是否会记住“主题”块?
【发布时间】:2013-10-27 01:59:03
【问题描述】:

我正在使用的编码标准规定,一组测试函数的规范应该有一个主题,即被调用的函数。它看起来像这样:

define User do
  context :foo do
    let(:user) { FactoryGirl.create(:user) }
    subject { user.foo }
    it { ... }
  end
end

subject 块的典型用途是实例化您正在测试的类:

define User do
  subject { FactoryGirl.create(:user) }
  it { ... }
end

我们的样式指南的预期效果是,我们为每个正在测试的方法设置了不同的主题块。这会减慢我们的测试速度吗?如果我们以典型方式使用subject,我们是否会受益于内置记忆或其他加速每个类只有一个主题块?

旁白:

我遇到过一种情况,我们的风格不起作用。使用any_instance.should_receive 时,您不能遵循我们的样式指南,否则规范将始终失败。相反,您需要使用更传统的方法,其中 subject 是您正在测试的对象,并在您的规范中调用它的方法。

# passing spec
define Foo do
  before { Bar.any_instance.stub(:baz) }
  subject { FactoryGirl.create(:foo) }
  it "bazzes Bars" do
    Bar.any_instance.should_receive(:baz)
    subject.baz_the_bars
  end
end

# spec follows style guide but fails
define Foo do
  before { Bar.any_instance.stub(:baz) }
  let(:foo) { FactoryGirl.create(:foo) }
  subject { foo.baz_the_bars }

  it "bazzes Bars" do
    Bar.any_instance.should_receive(:baz)
    subject
  end
end

class Foo
  has_many :bars

  def baz_the_bars
    bars.collect do |bar|
      bar.baz
    end.count(true)
  end
end

这种风格还有什么我应该注意的问题吗?

【问题讨论】:

  • 我可能遗漏了一些东西,为什么您的 Bar 存根会导致问题?主题尚未存在,因此仍应在方法运行之前设置断言。
  • before 块中,我没有存根Bar。我在Bar 的任何实例上存根方法baz()。我的第一遍是:before { Bar.stub(:baz) } 这也有效。但是,这并没有通过代码审查,所以我需要修改 before 块。
  • 抱歉,我不清楚 - 我的意思是在所有 Bars 上存根 baz。但是,我仍然不明白为什么您的测试失败。您能否更新您的示例以使其可运行? define 在这里不是有效的关键字,我认为您可以删除对 ActiveModel 和 FactoryGirl 的引用。也许这也会使问题更容易回答。

标签: rspec subject behaviorsubject


【解决方案1】:

subject 是按测试延迟创建的,并且作用域为context / describe,就像let 一样。他们不应该有任何额外的开销。

我个人不喜欢你展示的风格,但是当我有从方法返回的非常复杂(或只是大)数据对象时,我做过类似的事情。

describe "A thing" do
  subject(:foo) { FactoryGirl.create(:foo) }

  # A very complicated object from this method
  describe "the result of calling frob" do
    subject(:result) { foo.frob }

    it { should be_active }
    it { should be_alive }
  end
end

【讨论】:

  • 对不起,如果我的问题不清楚。我不是在问使用subject 是否有额外的开销。我在问是否有额外的开销来在任何地方使用相同的主题。基本上,主题是否有一些我们没有利用的记忆。我将编辑问题以尝试澄清。感谢您的回答。
  • 好吧,我也无意中回答了这个问题 - subject 在一次测试中被记住,但它是 per-test,所以它每次都会重置。您可能有数千个 subject 块(这将是一个坏主意 ^_^),并且唯一的额外时间将用于解析文件。
  • 谢谢。很高兴知道。我们确实有数千个subject 块。从来没有人问我这是否是一个坏主意,但事情就是这样完成的。只要团队意见一致,我不太在意我们做事与其他人不同。至少这是我试图告诉自己的:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-24
  • 2015-12-21
  • 1970-01-01
相关资源
最近更新 更多