2009-12-15 14 views

उत्तर

3

http://blog.ardes.com/2006/12/11/testing-singletons-with-ruby पर एक नजर है: "वैश्विक चर, बुरा कर रहे हैं m'kay"

require 'singleton' 

class <<Singleton 
    def included_with_reset(klass) 
    included_without_reset(klass) 
    class <<klass 
     def reset_instance 
     Singleton.send :__init__, self 
     self 
     end 
    end 
    end 
    alias_method :included_without_reset, :included 
    alias_method :included, :included_with_reset 
end 
+0

इसके साथ समस्या यह है कि, जब आपके परीक्षण चलते हैं तो वैश्विक स्थिति संशोधित होती है। एक क्लीनर तरीके के लिए नीचे मेरा जवाब देखें। –

0

RSpec आप पूर्व-परीक्षण कार्यों प्रदर्शन करते देता है? ऐसा है, आप स्थिर वर्ग के लिए एक और तरीका जोड़ सकते हैं जो कि कन्स्ट्रक्टर के दौरान किए गए कुछ भी साफ़ कर देता है। फिर बस प्रत्येक परीक्षण से पहले कॉल करें।

+0

आरएसपीईसी में "पहले" और "बाद" ब्लॉक हैं। http://rspec.info/documentation/before_and_after.html –

+1

लेकिन सिंगलटन पैटर्न की वजह से निर्माता को दो बार नहीं बुलाया जाएगा। – brainfck

1

इसे एक कक्षा में दोबारा दोहराएं जिसे कई बार बनाया जा सकता है। कक्षा से सिंगलटन प्रकृति को हटाने का इसका दुष्प्रभाव (कुछ लाभ होगा)।

इसे एक और तरीके से देखें: आपको एक से अधिक बार कन्स्ट्रक्टर को कॉल करने की आवश्यकता है। कक्षा केवल एक उदाहरण का निर्माण करना चाहिए? सिंगलटन क्या लाभ प्रदान करता है?

+0

कन्स्ट्रक्टर को एक से अधिक बार कॉल करने की आवश्यकता नहीं है, लेकिन मैं अपने चश्मे को स्पष्ट रखना चाहता हूं - इसलिए मैं प्रत्येक spec में कन्स्ट्रक्टर के केवल एक हिस्से का परीक्षण कर रहा हूं। – brainfck

-1

आप बस एक नया it बना सकते हैं और प्रत्येक स्पेक के लिए ब्लॉक कर सकते हैं। एक टेस्टेबल इकाई के लिए अपने spec तोड़ो। आपके द्वारा किए गए कुछ भी सेट अप और साफ़ करने के लिए "पहले" और "बाद" का उपयोग करें।

before(:each) और after(:each) प्रत्येक it ब्लॉक के लिए निष्पादित किए जाते हैं।

2

एक कारण लोगों क्योंकि एकमात्र का उपयोग एक सिंगलटन एक वैश्विक चर है, जो नाम स्थान में अनुक्रमित है, और आलसी तत्कालता के साथ। इस बात पर विचार करें कि क्या एक वास्तविक वैश्विक चर चीजों को सरल बना सकता है, खासकर अगर आपको आलसी तत्काल आवश्यकता नहीं है।

3

एक पैटर्न मैंने देखा है कि सिंगलटन वास्तविक वर्ग का उप-वर्ग है। आप उत्पादन कोड में सिंगलटन संस्करण का उपयोग करते हैं, लेकिन परीक्षण के लिए आधार (गैर-सिंगलटन) वर्ग।

उदाहरण:

class MyClass 
    attr_accessor :some_state 

    def initialize 
    @some_state = {} 
    end 
end 

class MySingletonClass < MyClass 
    include Singleton 
end 

... लेकिन मैं एक बेहतर तरीका के लिए देख रहा हूँ अपने आप को।

मेरी समस्या का एक हिस्सा यह है कि मैं जावा सिस्टम प्राथमिकताओं में JRuby का उपयोग कर रहा हूं और वैश्विक हैं। बाकी मुझे लगता है कि मैं फिर से प्रतिक्रिया कर सकता हूं।

7
# singleton_spec.rb 
require "singleton" 

class Global 
    include Singleton 

    def initialize 
    puts "Initializing" 
    end 
end 

describe Global do 
    before do 
    Singleton.__init__(Global) 
    end 

    it "test1" do 
    Global.instance 
    end 

    it "test2" do 
    Global.instance 
    end 
end 


% rspec singleton_spec.rb -fd 
Global 
Initializing 
    test1 
Initializing 
    test2 
+0

कुंजी "सिंगलटन .__ init __ (वैश्विक)" है। यह मेरे लिए इसे दबाया। धन्यवाद। – iHiD

+0

समस्या यह है कि यह सिंगलटन को रीसेट करता है। यदि आपके ऐप के किसी भी अन्य हिस्से वैश्विक स्थिति पर भरोसा करते हैं जो पहले सेट किया गया था, तो यह टूट जाएगा। उदाहरण के लिए, यदि आप रजिस्ट्री पैटर्न का उपयोग कर रहे हैं, तो रजिस्ट्री का उपयोग करने वाले घटकों के परीक्षणों को तोड़ने के बिना आप रजिस्ट्री का परीक्षण कैसे करते हैं? –

14

सिंगलटन कक्षाएं अनिवार्य रूप से ऐसा करते हैं

def self.instance 
    @instance ||= new 
end 

private_class_method :new 

तो तुम निजी विधि नई भेज

let(:instance) { GlobalClass.send(:new) } 

इस तरह के एक अच्छा लाभ यह है कि कोई है का उपयोग कर फोन करके पूरी तरह Memoization बायपास कर सकते हैं वैश्विक परीक्षण आपके परीक्षणों के परिणामस्वरूप संशोधित किया गया है।


शायद

एक बेहतर तरीका, this answer से:

let(:instance) { Class.new(GlobalClass).instance } 

ऐसा अनाम वर्ग जो GlobalClass से विरासत है, जो सभी वर्ग स्तर के उदाहरण चर में जमा हो जाती बनाता है यह तो प्रत्येक के बाद फेंक दी जाती है। परीक्षण, GlobalClass छूटे हुए छोड़कर।

+0

यह एक साधारण, सीधा समाधान है। –

+0

धन्यवाद, यह बहुत उपयोगी था। – chrisco

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