2015-04-01 8 views
31

बदलने की उम्मीद है मैं एक विशेषता में एक फॉर्म जमा करते समय मॉडल में कई बदलावों की जांच करना चाहता हूं। उदाहरण के लिए, मैं यह सुनिश्चित करना चाहता हूं कि उपयोगकर्ता का नाम एक्स से वाई में बदला गया था, और एन्क्रिप्टेड पासवर्ड किसी भी मूल्य से बदला गया था।आरएसपीसी: एकाधिक

मुझे पता है कि पहले से ही इसके बारे में कुछ प्रश्न हैं, लेकिन मुझे मेरे लिए उपयुक्त जवाब नहीं मिला। सबसे सटीक उत्तर माइकल जॉनस्टन द्वारा ChangeMultiple मैचर की तरह लगता है: Is it possible for RSpec to expect change in two tables?। इसका नकारात्मक पक्ष यह है कि केवल ज्ञात मूल्यों से ज्ञात मूल्यों में स्पष्ट परिवर्तनों की जांच करें।

module RSpec 
    module Matchers 
    def change_multiple(receiver=nil, message=nil, &block) 
     BuiltIn::ChangeMultiple.new(receiver, message, &block) 
    end 

    module BuiltIn 
     class ChangeMultiple < Change 
     def with_expectations(expectations) 
      # What to do here? How do I add the expectations passed as argument? 
     end 
     end 
    end 
    end 
end 

लेकिन अब:

expect { 
    click_button 'Save' 
}.to change_multiple { @user.reload }.with_expectations(
    name:    {from: 'donald', to: 'gustav'}, 
    updated_at:   {by: 4}, 
    great_field:  {by_at_leaset: 23}, 
    encrypted_password: true, # Must change 
    created_at:   false, # Must not change 
    some_other_field: nil # Doesn't matter, but want to denote here that this field exists 
) 

मैं भी इस तरह ChangeMultiple मिलान के बुनियादी कंकाल बनाया है:

मुझे लगता है मैं कैसे लगता है की तरह एक बेहतर मेल खाने वाला लग सकता है पर कुछ छद्म कोड बनाया मुझे पहले से ही यह त्रुटि मिल रही है:

Failure/Error: expect { 
    You must pass an argument rather than a block to use the provided matcher (nil), or the matcher must implement `supports_block_expectations?`. 
# ./spec/features/user/registration/edit_spec.rb:20:in `block (2 levels) in <top (required)>' 
# /Users/josh/.rvm/gems/[email protected]/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load' 
# /Users/josh/.rvm/gems/[email protected]/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `block in load' 

थाई बनाने में कोई मदद एस कस्टम matcher अत्यधिक सराहना की है।

उत्तर

62

आरएसपीसी 3 में आप एक साथ कई स्थितियों को सेट कर सकते हैं (इसलिए एकल उम्मीद नियम टूटा नहीं गया है)। यह देखने के sth तरह होगा:

expect { 
    click_button 'Save' 
    @user.reload 
}.to change { @user.name }.from('donald').to('gustav') 
.and change { @user.updated_at }.by(4) 
.and change { @user.great_field }.by_at_least(23} 
.and change { @user.encrypted_password } 

यह एक पूर्ण समाधान हालांकि नहीं है - जहाँ तक मेरी अनुसंधान चला गया वहाँ कोई आसान तरीका अभी तक and_not करना है। मैं आपकी आखिरी जांच के बारे में भी अनिश्चित हूं (अगर इससे कोई फर्क नहीं पड़ता, तो इसका परीक्षण क्यों करें?)। स्वाभाविक रूप से आप इसे अपने custom matcher के भीतर लपेटने में सक्षम होना चाहिए।

+4

अगर आप उम्मीद करते हैं कि कई चीजों * नहीं कर रहे हैं * बदल चाहते हैं, बस '.and change {@something} का उपयोग करें .by (0) ' –

+0

क्या आप सभी कोष्ठक के साथ दूसरा उदाहरण जोड़ सकते हैं? मुझे समझना मुश्किल है कि कौन सी विधियां जंजीर हैं –

4

यदि आप परीक्षण करना चाहते हैं कि एकाधिक रिकॉर्ड नहीं बदले गए हैं, तो आप RSpec::Matchers.define_negated_matcher का उपयोग करके एक मैचर को घुमा सकते हैं। इसलिए, आपकी फ़ाइल के शीर्ष पर

RSpec::Matchers.define_negated_matcher :not_change, :change 

जोड़ने (या अपने rails_helper.rb) और फिर आप and का उपयोग कर श्रृंखला कर सकते हैं:

expect{described_class.reorder}.to not_change{ruleset.reload.position}. 
    and not_change{simple_ruleset.reload.position}