如何将实例变量传递给RSpec共享示例

Geo*_*haw 35 ruby-on-rails rspec2

我正在使用RSpec(2.10.1)来测试模型上的验证,并提取了一些代码以与其他模型验证共享.验证首先写在Companies表上,因此代码如下所示:

# support/shared_examples.rb
shared_examples "a text field" do |field, fill, length|
  it "it should be long enough" do
    @company.send("#{field}=", fill * length)
    @company.should be_valid
  end

  etc...
end
Run Code Online (Sandbox Code Playgroud)

用法是:

# company_spec.rb
describe Company do
  before { @company = Company.new( init stuff here ) }

  describe "when address2" do
    it_behaves_like "a text field", "address2", "a", Company.address2.limit
  end

  etc...
end
Run Code Online (Sandbox Code Playgroud)

我想@company将参数作为参数传递给共享示例,以便我可以将代码重用于不同的模型,如下所示:

# support/shared_examples.rb
shared_examples "a text field" do |model, field, fill, length|
  it "it should be long enough" do
    model.send("#{field}=", fill * length)
    model.should be_valid
  end

  etc...
end
Run Code Online (Sandbox Code Playgroud)

用法是:

# company_spec.rb
describe Company do
  before { @company = Company.new( init stuff here ) }

  describe "when address2" do
    it_behaves_like "a text field", @company, "address2", "a", Company.address2.limit
  end

  etc...
end
Run Code Online (Sandbox Code Playgroud)

但是,当我这样做时,我得到了undefined method 'address2' for nil:NilClass.它似乎@company没有通过(不在范围内?)我如何得到这样的东西工作?

Myr*_*ton 53

问题是self示例组self内部与before钩子内部不同,因此即使它具有相同的名称,它也不是相同的实例变量.

我建议您使用let以下情况:

# support/shared_examples.rb
shared_examples "a text field" do |field, fill, length|
  it "it should be long enough" do
    model.send("#{field}=", fill * length)
    model.should be_valid
  end
end

# company_spec.rb
describe Company do
  describe "when address2" do
    it_behaves_like "a text field", "address2", "a", Company.address2.limit do
      let(:model) { Company.new( init stuff here ) }
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 在RSpec中有两个基本值`self`,它类似于ruby类定义中self的两个值.在`describe` /`context` /`shared_examples_for`和它对应的`end`之间(但不在`it`块中),`self`是示例组 - 就像类体中的`self`一样(但是不在方法定义中)是类本身.在`it` /`let`块或`before` /`after` /`around`钩子中的`self`或者是示例 - 就像类中的`self`一样,实例方法定义是类的实例. (6认同)
  • 另一种思考方式:RSpec执行的是两次传递过程.首先,它评估所有嵌套的`describe` /`context` /`shared_examples_for`块,以便定义所有的例子; 在这一点上,这些上下文中的`self`是相应的示例组.其次,RSpec运行所有定义的示例(`it`块).每个定义的示例都在相应示例组的实例中进行评估,并且`self`就是示例. (3认同)