2014-09-10 8 views
6

मुझे example_double का उपयोग करते समय अंतःक्रियात्मक परीक्षण विफलताओं मिल रही है।रुपयेपीईसी इंस्टेंस_डब्लूएल इंटरमीटेंट स्पेक असफलता

मेरे पास 4 चश्मे वाली एक फ़ाइल है। यहां स्रोत है:

require 'rails_helper' 

describe SubmitPost do 
    before(:each) do 
    @post = instance_double('Post') 
    allow(@post).to receive(:submitted_at=) 
    end 

    context 'on success' do 
    before(:each) do 
     allow(@post).to receive(:save).and_return(true) 

     @result = SubmitPost.call(post: @post) 
    end 

    it 'should set the submitted_at date' do 
     expect(@post).to have_received(:submitted_at=) 
    end 

    it 'should call save' do 
     expect(@post).to have_received(:save) 
    end 

    it 'should return success' do 
     expect(@result.success?).to eq(true) 
     expect(@result.failure?).to eq(false) 
    end 
    end 

    context 'on failure' do 
    before(:each) do 
     allow(@post).to receive(:save).and_return(false) 

     @result = SubmitPost.call(post: @post) 
    end 

    it 'should return failure' do 
     expect(@result.success?).to eq(false) 
     expect(@result.failure?).to eq(true) 
    end 
    end 

end 

यह एक रेल 4.1.4 एप्लिकेशन है। आंतरिक रूप से, सबमिटपोस्ट सबमिट_ट और पास-इन पोस्ट पर कॉल सहेजता है। मेरे पोस्ट मॉडल इस तरह दिखता है:

class Post < ActiveRecord::Base 

    validates :title, presence: true 
    validates :summary, presence: true 
    validates :url, presence: true 
    validates :submitted_at, presence: true 

    scope :chronological, -> { order('submitted_at desc') } 

end 

यह सुपर वेनिला है।

जब मैं rake, rspec, या bin/rspec चलाता हूं, तो मुझे लगता है कि सभी चार परीक्षण 20% - 30% समय में विफल हो जाते हैं। त्रुटि संदेश हमेशा होता है:

Failure/Error: allow(@post).to receive(:submitted_at=) 
    Post does not implement: submitted_at= 

अगर मैं focus: true साथ चश्मा में से एक लेबल है, कि एक युक्ति समय की 100% असफल हो जायेगी।

यदि मैं को double के साथ प्रतिस्थापित करता हूं, तो सभी चश्मे 100% सफल होंगे।

ऐसा प्रतीत होता है कि example_double को पोस्ट क्लास पर उपलब्ध विधियों का उल्लंघन करने में कुछ कठिनाई हो रही है। यह कुछ हद तक यादृच्छिक और समय-आधारित प्रतीत होता है।

क्या कोई इस मुद्दे में भाग लेता है? कोई अंदाज़ा कि क्या गलत हो सकता है? समस्या निवारण के बारे में कैसे जाना है इसका कोई अर्थ? स्वाभाविक रूप से, एक डिबगिंग ब्रेकपॉइंट डालने से चश्मा 100% गुजरता है।

+0

मेरे पास इस पर कुछ और डेटा है। इस मुद्दे की जड़ यह है कि इस spec चलाते समय रेल पर्यावरण लोड नहीं किया जा रहा है। अगर मैं सिर्फ यह फ़ाइल चलाता हूं, तो यह हमेशा विफल रहता है। मेरे पास कुल चार spec फ़ाइलें हैं I अगर यह फ़ाइल पहले चलती है, तो यह विफल हो जाती है। अगर कुछ और पहले चलता है, तो यह सफल होता है। मेरी धारणा यह है कि पहले की दौड़ रेल पर्यावरण को लोड कर रही है, इसलिए यह परीक्षण गुजरता है। यह परीक्षण फ़ाइल 'spec/interactors' में स्थित है, ताकि समस्या में योगदान हो। – EricM

+0

अधिक डेटा। मैंने सत्यापित किया कि ऐप/इंटरैक्टर्स, जहां सबमिटपोस्ट रहता है, eager_load_paths में है। मैंने spec को टैग के साथ टैगिंग करने का भी प्रयास किया:: सुविधा। त्रुटि संदेश अपरिवर्तित है। – EricM

उत्तर

4

जो समस्या आप देख रहे हैं वह यह है कि ActiveRecord गतिशील रूप से कॉलम विधियों को बनाता है। instance_double'Post' का उपयोग यह सत्यापित करने के तरीकों को देखने के लिए करता है कि आप उन्हें सही तरीके से दबा रहे हैं (जब तक कि कक्षा अभी तक मौजूद न हो या लोड नहीं हो)।

जब कोई पूर्व स्पेस मॉडल लोड करता है, तो ActiveRecord उन गतिशील विधियों को बनाएगा, इसलिए आपका स्पेस आरएसपीईसी के रूप में गुजरता है, फिर विधियों को ढूंढ सकता है (respond_to? कॉल के साथ)। जब अलगाव में चलाया जाता है तो मॉडल का पहले उपयोग नहीं किया गया था और इसलिए ActiveRecord ने गतिशील विधियों को अभी तक नहीं बनाया होगा और आपका परीक्षण विफल होने पर आपका परीक्षण विफल हो जाएगा।

इस के लिए वैकल्पिक हल गतिशील तरीकों लोड करने के लिए ActiveRecord मजबूर करने के लिए जब वे अपनी कल्पना में कहा जाता है है:

class Post < ActiveRecord::Base 
    def submitted_at=(value) 
    super 
    end 
end 

देखें अधिक विवरण और समस्या के लिए समाधान के लिए RSpec प्रलेखन:

https://www.relishapp.com/rspec/rspec-mocks/docs/verifying-doubles/dynamic-classes

+0

मुझे इस समस्या को हल मदद के लिए धन्यवाद, मैं में वर्ग खोला एक 'से पहले (: संदर्भ) कर वर्ग MyClass ryan2johnson9

+0

मेरी उपरोक्त टिप्पणी फिर से करें। मैंने काम किया क्यों डबल ("MyClass") बेहतर है तो MyClass.new stubbing के लिए। उत्तरार्द्ध आपको कुछ भी स्टब करने की अनुमति देगा, इसलिए यदि आप उस कोड में विधि का नाम बदलते हैं जिसे आप spec में दबा रहे हैं, तो यह spec में विफल नहीं होता है और आपको झूठी सकारात्मक मिलती है। example_double का उपयोग करके एक अच्छी त्रुटि बढ़ जाती है। MyClass.new के साथ समान प्रभाव प्राप्त करने के लिए आपको इस तरह की अपेक्षा (my_double) जैसी विधि को रोकने से पहले spec में एक पंक्ति भी होनी चाहिए। प्रतिक्रिया_to ('the_method_i_am_about_to_stub') ' – ryan2johnson9

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