2012-10-23 24 views
6

मेरे पास दो वर्ग हैं:रेल के साथ और बिना फास्ट (रुपेक) परीक्षण

1. सेल ActiveRecord का उप-वर्ग है; इसका काम डेटाबेस में बिक्री डेटा जारी रखना है।

class Sale < ActiveRecord::Base 
    def self.total_for_duration(start_date, end_date) 
    self.count(conditions: {date: start_date..end_date}) 
    end 
    #... 
end 

2. सेलसपोर्ट एक मानक रूबी वर्ग है; इसका काम बिक्री के बारे में जानकारी तैयार करना और ग्राफ करना है।

class SalesReport 
    def initialize(start_date, end_date) 
    @start_date = start_date 
    @end_date = end_date 
    end 

    def sales_in_duration 
    Sale.total_for_duration(@start_date, @end_date) 
    end 
    #... 
end 

क्योंकि मैं TDD उपयोग करना चाहते हैं और मैं अपने परीक्षण चलाने के लिए वास्तव में तेजी से, मैं SalesReport के लिए एक युक्ति है कि रेल नहीं लोड नहीं करता है लिखा है चाहता हूँ:

require_relative "../../app/models/sales_report.rb" 

class Sale; end 
# NOTE I have had to re-define Sale because I don't want to 
# require `sale.rb` because it would then require ActiveRecord. 

describe SalesReport do 
    describe "sales_in_duration" do 
    it "calls Sale.total_for_duration" do 
     Sale.should_receive(:total_for_duration) 
     SalesReport.new.sales_in_duration 
    end 
    end 
end 

यह परीक्षण काम करता है जब मैं bundle exec rspec spec/models/report_spec.rb चलाता हूं।

हालांकि यह परीक्षण विफल रहता है जब मैं त्रुटि के साथ bundle exec rake spec चलाता हूं। मुझे पता है कि त्रुटि हो रही है क्योंकि टैप को sale.rb द्वारा परिभाषित किया गया है और spec के भीतर इनलाइन है।

तो मेरा प्रश्न स्टब (या नकली या डबल) कक्षा में एक वर्ग है यदि उस वर्ग को परिभाषित नहीं किया गया है? यह मुझे इनलाइन class Sale; end को हटाने की अनुमति देगा, जो एक हैक जैसा लगता है।

यदि नहीं, तो मैं अपने परीक्षण कैसे स्थापित करूं ताकि वे सही ढंग से चल सकें कि क्या मैं bundle exec rspec या bundle exec rake spec चलाता हूं?

यदि नहीं, तो तेजी से परीक्षण लिखने का मेरा दृष्टिकोण गलत है ?!

अंत में, मैं स्पार्क का उपयोग नहीं करना चाहता। धन्यवाद!

उत्तर

4

RSpec के हाल ही में stub_const जोड़ा है विशेष रूप से इन मामलों के लिए डिज़ाइन किया गया:

describe SalesReport do 
    before { stub_const("Sale", Class.new) } 

    describe "sales_in_duration" do 
    it "calls Sale.total_for_duration" do 
     Sale.should_receive(:total_for_duration) 
     SalesReport.new.sales_in_duration 
    end 
    end 
end 

आप 012 का भी उपयोग करना चाह सकते हैंSale के स्थान पर एक परीक्षण डबल का उपयोग करने के लिए जो वास्तविक Sale कक्षा पर वास्तविक रूप से सभी मॉक/स्टब किए गए विधियों की जांच करता है, वास्तविक Sale वर्ग लोड (उदा। जब आप अपने टेस्ट स्वीट) चलाएँ:

require 'rspec/fire' 

describe SalesReport do 
    include RSpec::Fire 

    describe "sales_in_duration" do 
    it "calls Sale.total_for_duration" do 
     fire_replaced_class_double("Sale") 
     Sale.should_receive(:total_for_duration) 
     SalesReport.new.sales_in_duration 
    end 
    end 
end 

आप वास्तविक Sale वर्ग पर total_for_duration नाम बदलते हैं, rspec विराम आप एक त्रुटि जब आप विधि नकली के बाद से यह वास्तविक वर्ग पर मौजूद नहीं है दे देंगे।

+0

धन्यवाद माइरॉन मार्स्टन! – Mike

4

एक आसान तरीका जाँच करने के लिए हो सकता है अगर "बिक्री" पहले से ही परिभाषित किया गया है

unless defined?(Sale) 
    class Sale; end 
end 

बिक्री के एक वर्ग या तो अपने परीक्षण में ऐसा होने की जरूरत नहीं:

unless defined?(Sale) 
    Sale = double('Sale') 
end 
+0

धन्यवाद। उम्मीद तो दिखती है। – Mike