RSpec测试在rails中引发异常

时间:2016-10-26 05:14:39

标签: ruby-on-rails ruby rspec exception-handling

我是RSpec的新手。我的模型user_profile.rb中有一个方法

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表中,我只有一列:name。

如何在user_profile.save失败时测试案例? 这里最重要的问题是我找不到任何方法让这个user_profile.save失败。

有人建议使用RSpec Stubs。我们怎么做?

2 个答案:

答案 0 :(得分:2)

根据Rspec的预期,当您预期会出现错误时,您会有一种特殊的语法。

如果你做了这样的事情:

 private static RequestQueue mRequestQueue;

 public RequestQueue getRequestQueue()
 {
    if (mRequestQueue == null) {
        Cache cache = new DiskBasedCache(MTXApplication.getAppContext().getCacheDir(), 20 * 1024 * 1024);
        Network network = new BasicNetwork(new HurlStack());
        mRequestQueue = new RequestQueue(cache, network);
        mRequestQueue.start();
    }
    return mRequestQueue;

}

这不起作用 - RSpec不会处理错误并退出。

但是如果使用括号:

expect(raise NoMethodError).to raise_error(NoMethodError)

应该通过。

如果你使用括号(或do / end块),那么块中的任何错误都将被“捕获”,你可以使用expect { raise NoMethodError }.to raise_error(NoMethodError) 匹配器进行检查。

答案 1 :(得分: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
  2. 此处user_details_str可能是无效的字符串格式(不是nil),因为从'auth_supplement/supplement_data/content'获得的内容格式不正确。

    1. user_details_xml = Nokogiri.parse(user_details_str)
    2. 在这里,您需要确定可能导致Nokogiri::parse给您无效结果的原因。

      1. user_name = user_details_xml.%('username').inner_html
      2. 然后在这里,与上面相同。

        1. user_profile = UserProfile.find_or_initialize_by(name: user_name)
        2. 所以在这里,由于之前的几行代码,您可能会有一个无效的user_name,这违反了您可能拥有的任何验证(例如,太短,没有大写,或者没有)。

          更多信息

          因此,这可以深入到您的代码中。很难测试,因为你的方法试图做太多。这显然违反了abc大小(逻辑分支太多,这里有更多信息:http://wiki.c2.com/?AbcMetric

          我建议将此方法的某些分支重构为较小的单一责任方法。