2012-05-11 11 views
3

次のコードは動作しませんが、それは最高の私はまた私が対象と を初期化し、内部コンテキスト内のローカル変数を使用しようとしたRspecで周辺コンテキストの件名にアクセスできますか?

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 

達成しようとしているかを示す、ありません運。内部スコープの対象定義内から外部スコープの対象にアクセスする方法はありますか?明らかに内側の文脈インスタンス変数を使用して、代わりにsubjectしかしsubject.callではない、それを初期化している作品

答えて

0

何か。科目はProcsです。したがって、私の最初のアプローチは機能しませんでした。

context "instances of this class" do 

    klass = subject.call 
    subject { klass.new } 

end 
3

#subjectを使用すると、問題が発生することがあります。これは#itsのような短手小切手での使用を「主に意図した」ものです。

また、テストする名前/意図をマスクするために、読みにくい例を作ることもできます。ここでデビッドChelimskyが#subjectと#letと意思を明らかに果たす役割のトピックに書いたブログ記事があります:http://blog.davidchelimsky.net/blog/2012/05/13/spec-smell-explicit-use-of-subject/

ここでは代わりに 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

0

私はこれに対する解決策を探していましたが、さまざまな理由がありました。値を返すかエラーを発生させるメソッドをテストすると、しばしばraise_errorのprocとして2回、通常は1回、2つのコンテキストで繰り返します。

letsのようにsubjectsの名前を付けることができます。これは、新しい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 
関連する問題