2011-04-05 10 views
32

स्कॉप करने दें मुझे विश्वास है कि मुझे rspec let and scoping के साथ कोई समस्या है। मैं उदाहरणों ("इसे" ब्लॉक) में परिभाषित विधियों का उपयोग कर सकता हूं, लेकिन बाहर नहीं (वर्णन ब्लॉक जहां मैंने दिया था)।रुपेक

connection_spec.rb:10: undefined local variable or method `connection' for Class:0xae8e5b8 (NameError)

मैं कैसे it_behaves_like के लिए कनेक्शन पैरामीटर पारित कर सकते हैं:

5 describe Connection do 
8  let(:connection) { described_class.new(connection_settings) } 
9 
10 it_behaves_like "any connection", connection 
24 end 

जब मैं इस कल्पना चलाने का प्रयास, मैं त्रुटि मिलती है?

उत्तर

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

क्या आरएसपीसी बंदरपैच 'नया' ऐसा करने के लिए करता है? –

19

रेडक्टेड - पूरी तरह से मेरे पहले समाधान पर whiffed। हो-शेंग हियाओ ने क्यों एक महान स्पष्टीकरण दिया।

आप 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 पर है, जहां यह साझा उदाहरणों तक पहुंचने से पहले इसे "कनेक्शन" से पहले मुठभेड़ करता है। दूसरा समाधान कोड को डुप्लिकेट करेगा, क्योंकि मुझे कनेक्शन_एसपीसी में उदाहरणों में कोड (: कनेक्शन) द्वारा कोड की आवश्यकता है। – Costi

+4

यह अब तक का बेहतर जवाब है। – robomc

+0

यह वास्तव में सही उत्तर – Dorian

27

देना() उदाहरण के ब्लॉक और व्यर्थ कहीं और के दायरे वाला हो जाता है। आप वास्तव में पैरा() पैरामीटर के रूप में उपयोग नहीं करते हैं। पैरामीटर के रूप में it_behaves_like के साथ काम नहीं करने का कारण यह है कि कैसे() परिभाषित किया जाता है। रुपयेपीसी में प्रत्येक उदाहरण समूह एक कस्टम वर्ग को परिभाषित करता है। चलो() उस वर्ग में एक उदाहरण विधि परिभाषित करता है। हालांकि, जब आप उस कस्टम क्लास में 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 

उन साझा उदाहरण की परिभाषा साझा उदाहरणों का उपयोग करने से अधिक verbose हैं। मुझे लगता है कि मुझे "it_behave_like" सीधे रुपेक को विस्तारित करने से अधिक अजीब लगता है।

जाहिर है, आप .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 और वैरिएबल के बीच "कनेक्शन" नाम के साथ निर्भरता बनाते हैं। इसलिए, यदि आपके पास किसी अन्य spec में एक let (: new_connection) है, तो यह काम नहीं करेगा। –

संबंधित मुद्दे