Rspecletとスコープに問題があると思います。 let inの例(「it」ブロック)で定義されたメソッドを使用できますが、外部(letを実行したdescribeブロック)では使用できません。
5 describe Connection do
8 let(:connection) { described_class.new(connection_settings) }
9
10 it_behaves_like "any connection", connection
24 end
この仕様を実行しようとすると、次のエラーが発生します。
connection_spec.rb:10:クラス:0xae8e5b8の未定義のローカル変数またはメソッド `connection '(NameError)
接続パラメータをit_behaves_likeに渡すにはどうすればよいですか?
私は自分に合ったものを見つけました:
describe Connection do
it_behaves_like "any connection", new.connection
# new.connection: because we're in the class context
# and let creates method in the instance context,
# instantiate a instance of whatever we're in
end
let()は、サンプルブロックにスコープされ、他の場所では使用できないことになっています。実際には、let()をパラメーターとして使用しません。パラメータとしてit_behaves_likeで機能しない理由は、let()の定義方法に関係しています。 Rspecの各サンプルグループはカスタムクラスを定義します。 let()は、そのクラスのインスタンスメソッドを定義します。ただし、そのカスタムクラスでit_behaves_likeを呼び出すと、インスタンス内からではなく、クラスレベルで呼び出されます。
私は次のようにlet()を使用しました:
shared_examples_for 'any connection' do
it 'should have valid connection' do
connection.valid?
end
end
describe Connection do
let(:connection) { Connection.new(settings) }
let(:settings) { { :blah => :foo } }
it_behaves_like 'any connection'
end
Shared_examplesを使用することはめったにありませんが、bcobbの回答と同様のことを行いました。
module SpecHelpers
module Connection
extend ActiveSupport::Concern
included do
let(:connection) { raise "You must override 'connection'" }
end
module ClassMethods
def expects_valid_connection
it "should be a valid connection" do
connection.should be_valid
end
end
end
end
end
describe Connection do
include SpecHelpers::Connection
let(:connection) { Connection.new }
expects_valid_connection
end
これらの共有例の定義は、共有例を使用するよりも冗長です。 「it_behave_like」はRspecを直接拡張するよりも厄介だと思います。
明らかに、.expects_valid_connectionsに引数を追加できます
私は友人のrspecクラスを助けるためにこれを書きました: http://Ruby-lambda.blogspot.com/2011/02/agile-rspec-with-let.html .. ..
編集済み-私の最初の解決策を完全に説明しました。Ho-ShengHsiaoが理由について素晴らしい説明をしました。
it_behaves_like
に次のようなブロックを与えることができます。
describe Connection do
it_behaves_like "any connection" do
let(:connection) { described_class.new(connection_settings) }
end
end
let
で宣言されたパラメーターを明示的に渡さない場合、共有の例で使用できることを発見しました。
そう:
describe Connection do
let(:connection) { described_class.new(connection_settings) }
it_behaves_like "any connection"
end
接続は、共有のサンプル仕様で利用可能になります
これは私のために働きます:
describe "numbers" do
shared_examples "a number" do |a_number|
let(:another_number) {
10
}
it "can be added to" do
(a_number + another_number).should be > a_number
end
it "can be subtracted from" do
(a_number - another_number).should be < a_number
end
end
describe "77" do
it_should_behave_like "a number", 77
end
describe "2" do
it_should_behave_like "a number", 2
end
end