2012-07-06 7 views
35

RSpec(2.10.1)を使用してモデルの検証を行い、他のモデルの検証と共有するコードを抽出しました。インスタンス変数をRSpec共有例に渡す方法

# 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 

と使用方法は次のとおりです:

# 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 

私は共有にパラメータとして@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 

と使用方法は次のとおりです。

# 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 

ただし、これを行うとundefined method 'address2' for nil:NilClassとなります。 @companyが渡されていないようです(範囲内ではありません)どうすればこのようなことができますか?

答えて

49

例グループ内のselfは、beforeフック内でselfと異なるため、同じ名前を持っていても同じインスタンス変数ではありません。

私はあなたがこのような場合のために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 
+1

いくつかの作品は、私には意味がありません。 「自己」が違うなら、どこが違うのですか? '@ company.send()'と '@ company.should'は' shared_examples'で動作するのはなぜですか?あなたの提案では、 'Company.new()'を '@ company'(これは' before'ブロックを維持)に置き換えることができ、それは動作します。私の理解は、ここで何が起こっているのかについて何か不足しています。特定の場所( 'it_behaves_like'から' do'までの行)で 'self 'だけが異なるようです。 –

+6

RSpecには 'self'という2つの基本的な値があり、ルビクラス定義のselfの2つの値に似ています。 'describe' /' context'/'shared_examples_for'とそれに対応する' end'( 'it'ブロックではありません)の間に、' self'がクラスのボディの 'self'のようなグループの例ですメソッド定義ではない)はクラスそのものです。 'それ'/'let'ブロックや' before'/'after' /' around'フックの中の 'self'や例です - クラスのインスタンスメソッド定義の' self'と同じようにクラスのインスタンスです。 –

+3

それを考えるもう一つの方法:RSpecが実行する2回のプロセスがあります。まず、すべての例を定義するために、すべてのネストされた 'describe' /' context'/'shared_examples_for'ブロックを評価します。この時点で、これらの文脈における 'self'は、対応するサンプルグループです。次に、RSpecはすべての定義された例を実行します( 'it'ブロック)。定義された各例は、対応するサンプルグループのインスタンスで評価され、 'self'が例です。 –

関連する問題