2011-04-05 48 views
32

我相信我有rspec let和範圍的問題。我可以使用let實例中定義的方法(「it」塊),但不能在外面(我所做的描述塊)。Rspec讓範圍

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: undefined local variable or method `connection' for Class:0xae8e5b8 (NameError)

如何傳遞連接參數的it_behaves_like?

回答

3

我發現我是什麼在起作用:

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 
+0

RSpec monkeypatch'new'做到這一點嗎? – 2011-04-10 23:13:42

19

編輯 - 在我的第一個解決方案中完全被吹響了。何何生爲什麼給了一個很好的解釋。

可以給it_behaves_like塊,像這樣:

describe Connection do 
    it_behaves_like "any connection" do 
    let(:connection) { described_class.new(connection_settings) } 
    end 
end 
+0

我 「shared_examples_for」 任何連接可用 「|連接|做」。該錯誤在第10行,它在第一行遇到「連接」時嘗試它,然後到達共享示例。第二種解決方案將複製代碼,因爲我需要在connection_spec的示例中使用let(:connection)代碼。 – Costi 2011-04-05 18:15:11

+4

這是迄今爲止最好的答案。 – robomc 2013-01-29 03:58:21

+0

這實際上是正確答案 – Dorian 2014-10-01 14:59:28

27

設()應該先限定的示例框和不可用的其它地方。您實際上不使用let()作爲參數。它不能與it_behaves_like一起作爲參數的原因與let()被定義的方式有關。 Rspec中的每個示例組都定義了一個自定義類。 let()在該類中定義了一個實例方法。但是,當您在該自定義類中調用it_behaves_like時,它將在類級調用,而不是在實例內調用。

我用設()是這樣的:

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 

我做過類似的東西,以bcobb的答案,但我很少用shared_examples:

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 ...

1

這適用於我:

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 
6

我發現如果您不明確傳遞let聲明的參數,它將在共享示例中可用。

所以:

describe Connection do 
    let(:connection) { described_class.new(connection_settings) } 

    it_behaves_like "any connection" 
end 

連接將在共享例如規格

+0

這個工程,但它不好。您在shared_context和名爲「connection」的變量之間創建一個依賴關係。所以,如果你在另一個規範中有一個let(:new_connection),它將不起作用。 – 2016-05-20 18:50:24