2016-10-26 94 views
0

我是RSpec的新手。我在我的模型user_profile.rbRSpec測試在rails中引發異常

def self.create_from_supplement(device, structure) 
    xml = Nokogiri.parse(structure.to_s) 
    user_profile = nil 
    auth_type = xml.%('auth_supplement/auth_type').inner_html 

    if 'user' == auth_type 
    user_details_str = xml.%('auth_supplement/supplement_data/content').inner_html rescue nil 

    return nil if user_details_str.blank? 

    user_details_xml = Nokogiri.parse(user_details_str) 
    user_name = user_details_xml.%('username').inner_html 

    user_profile = UserProfile.find_or_initialize_by(name: user_name) 

    if user_profile.save 
     device.update_attributes(user_profile_id: user_profile.id) 
    else 
     raise "User Profile Creation Failed because of #{user_profile.errors.full_messages}" 
    end 

    end 

    return user_profile 
end 

我寫一個單元測試用例時user_profile.save無法測試方法,測試案例會想到一個異常升高。但在我的user_profiles表中,我只有一列:名稱。

如何測試user_profile.save失敗時的情況? 這裏最重要的問題是我沒有找到任何辦法讓這個user_profile.save失敗。

一些建議使用RSpec存根。我們如何做到這一點?

回答

0

結賬rspec的文件:

https://www.relishapp.com/rspec/rspec-expectations/v/2-11/docs/built-in-matchers/raise-error-matcher

describe ':: create_from_supplement' do 
    it 'blows up' do 
    expect { UserProfile.create_from_supplement(*args) }.to raise_error(/User Profile Creation Failed because of/) 
    end 
end 

追溯你的代碼,這裏有可能會導致錯誤的地方,下面你可以考慮一下。

  1. user_details_str = xml.%('auth_supplement/supplement_data/content').inner_html

這裏user_details_str可能是一個無效的字符串格式(不爲零),因爲無論你從'auth_supplement/supplement_data/content'得到的是不是一個正確的格式。

  • user_details_xml = Nokogiri.parse(user_details_str)
  • 在這裏,你需要確定什麼可能導致Nokogiri::parse給你一個無效的結果。

  • user_name = user_details_xml.%('username').inner_html
  • 然後在這裏,與上述相同。

  • user_profile = UserProfile.find_or_initialize_by(name: user_name)
  • 所以在這裏,你可能有一個無效的user_name由於代碼的前幾行,違反你可能有(例如太短任何驗證,沒有大寫,或者不是)。

    更多信息

    因此,這可以更深入你的代碼。這很難測試,因爲你的方法試圖做太多。這顯然違反了ABC尺寸(邏輯分支太多,這裏有更多信息:http://wiki.c2.com/?AbcMetric

    我建議將此方法的一些分支重構爲較小的單一責任方法。

    +0

    這裏的問題是如何讓user_profile.save失敗? – krishna

    +0

    @krishna看到我編輯的答案 –

    1

    隨着Rspec的期望,你有一個特殊的語法,當你期望錯誤被提出。

    ,如果你做了這樣的事情:

    expect(raise NoMethodError).to raise_error(NoMethodError) 
    

    那就沒辦法了 - RSpec的不處理錯誤,並會退出。

    但是如果你用括號:

    expect { raise NoMethodError }.to raise_error(NoMethodError) 
    

    應該通過。

    如果使用方括號(或do/end塊),則塊中的任何錯誤都將被「捕獲」,您可以使用raise_error匹配器來檢查它們。

    相關問題