2016-04-19 28 views
6

多個not_to改革的期望,我想,以確保一定的數據具有通過一個單一的動作保持不變:預計rspec的

expect { 
    # running migration and user reload here 
}.not_to change(user, :avatar_url).from(sample_avatar_url).and change(user, :old_avatar).from(nil) 

sample_avatar_url是在規範文件的開頭定義的字符串。

基本上,我想檢查avatar_urlold_avatar是否仍然未被expect塊中發生的情況觸發。

從上面的代碼的輸出是:

expect(...).not_to matcher.and matcher不被支持,因爲它產生一個比特的模糊性。相反,定義否定版本的任何匹配你想否定與RSpec::Matchers.define_negated_matcher和使用expect(...).to matcher.and matcher

回答

11

這不起作用,因爲它不清楚閱讀是否應該意味着不改變第一,不改變第二,或不改變第一,但改變第二。你有幾個選項來解決這個問題

既然你檢查的靜態值只是不使用變化

..run migration and user reload.. 
expect(user.avatar_url).to eq(sample_avatar_url) 
expect(user.old_avatar).to eq nil 

或define_negated_matcher用於創建not_change匹配

RSpec::Matchers.define_negated_matcher :not_change, :change 
expect { 
    # running migration and user reload here 
}.to not_change(user, :avatar_url).from(sample_avatar_url).and not_change(user, :old_avatar).from(nil) 
+0

與第一例子簡化它的伎倆。謝謝! – abpetkov

+0

不客氣 - 只是注意,檢查略少一點,因爲它只檢查是否設置了特定的值,而不是它從其他值改變爲該值 - 如果這足以對您的用例進行測試,那麼它的效果很好。 –

+0

在rails_helper.rb中放置'RSpec :: Matchers.define_negated_matcher(:not_change,:change)'給了我的RSpec superpowers。 – Epigene

0

由於在托馬斯的答案中說,它不起作用,因爲它不清楚閱讀,你可以創建一個否定匹配器。另一種選擇是使用saharspec gem及其dont匹配器否定。

下面是該項目的自述文件的摘錄:

另一個(實驗)試圖擺脫define_negated_matcherdont在語法上不是100%正確的,但足夠短且可讀。它只是否定附加的匹配器。

# before 
RSpec.define_negated_matcher :not_change, :change 

it { expect { code }.to do_stuff.and not_change(obj, :attr) } 

# after: no `define_negated_matcher` needed 
require 'saharspec/matchers/dont' 

it { expect { code }.to do_stuff.and dont.change(obj, :attr) } 

所以,你可以寫你的期望,而無需創建一個否定匹配這樣的:

expect { 
    # running migration and user reload here 
}.to dont.change(user, :avatar_url).from(sample_avatar_url).and 
    dont.change(user, :old_avatar).from(nil)