1

我按照Everyday Rails Testing with RSpec一书中的示例创建了一个自定义 RSpec 匹配器,用于重定向到登录页面(requires_login匹配器)。该匹配器的代码如下所示:

RSpec::Matchers.define :require_login do

  match do |actual|
    redirect_to Rails.application.routes.url_helpers.login_path
  end

  failure_message_for_should do |actual|
    "expected to require login to access the method"
  end

  failure_message_for_should_not do |actual|
    "expected not to require login to access method"
  end

  description do
    "redirect to the login form"
  end

end

然后在下面的示例中调用此匹配器:

describe "GET #edit" do

  it "requires login" do
    user = FactoryGirl.create(:user)
    get :edit, id: user
    expect(response).to require_login
  end

end # End GET #edit

出于某种原因,上述测试有效,而以下测试无效(即使它也检查重定向到登录路径):

describe "GET #edit" do

  it "requires login" do
    user = FactoryGirl.create(:user)
    get :edit, id: user
    expect(response).to redirect_to login_path
  end

end # End GET #edit

我已经多次查看我的代码以及上面提到的书中的示例,但找不到任何错误。任何有关如何正确实现此匹配器的见解将不胜感激。我也在使用 Ruby 2.0.0、Rails 3.2.13 和 RSpec-Rails 2.13.1。

解决方案(感谢 Frederick Cheung 的建议)

RSpec::Matchers.define :require_login do |attribute|

  match do |actual|
    expect(attribute).to redirect_to Rails.application.routes.url_helpers.login_path
  end

  failure_message_for_should do |actual|
    "expected to require login to access the method"
  end

  failure_message_for_should_not do |actual|
    "expected not to require login to access method"
  end

  description do
    "redirect to the login form"
  end

end
4

1 回答 1

1

您的匹配块需要返回匹配是否匹配,但此时您返回的东西总是真实的。

您可能希望对 redirect_to 匹配器采用类似的方法,它调用提供的 railsassert_redirected_to并根据是否 ActiveSupport::TestCase::Assertion引发返回 true/false

于 2013-04-29T11:10:02.173 回答