RSpec测试使用GET参数重定向到URL

Sim*_*one 25 ruby parameters rspec ruby-on-rails response

假设我有FoosController一个redirect_to_baz方法.

class FoosController < ApplicationController

  def redirect_to_baz
    redirect_to 'http://example.com/?foo=1&bar=2&baz=3'
  end

end
Run Code Online (Sandbox Code Playgroud)

我正在测试这个spec/controllers/foos_controller_spec.rb:

require 'spec_helper'

describe FoosController, :type => :controller do

  describe "GET redirect_to_baz" do
    it "redirects to example.com with params" do
      get :redirect_to_baz
      expect(response).to redirect_to "http://example.com/?foo=1&bar=2&baz=3"
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

有用.但是,如果有人交换查询字符串参数(例如http://example.com/?bar=2&baz=3&foo=1),则测试失败.

测试这个的正确方法是什么?

我想做的事情如下:

expect(response).to redirect_to("http://example.com/", params: { foo: 1, bar: 2, baz: 3 })
Run Code Online (Sandbox Code Playgroud)

我查看了文档并尝试搜索response.parameters,但我没有找到类似的内容.甚至Hash#to_query似乎没有解决这个问题.

任何帮助将不胜感激.

hji*_*ing 27

文档中,预期的重定向路径可以匹配正则表达式:

expect(response).to redirect_to %r(\Ahttp://example.com)
Run Code Online (Sandbox Code Playgroud)

要验证重定向位置的查询字符串似乎有点复杂.您可以访问响应的位置,因此您应该能够这样做:

response.location
# => http://example.com?foo=1&bar=2&baz=3
Run Code Online (Sandbox Code Playgroud)

您应该能够像这样提取查询字符串参数:

redirect_params = Rack::Utils.parse_query(URI.parse(response.location).query)
# => {"foo"=>"1", "bar"=>"2", "baz"=>"3"}
Run Code Online (Sandbox Code Playgroud)

从中可以直接验证重定向参数是否正确:

expect(redirect_params).to eq("foo" => "1", "baz" => "3", "bar" => "2")
# => true
Run Code Online (Sandbox Code Playgroud)

如果你不得不多次执行这种逻辑,那么将它们全部包装到自定义的rspec匹配器中肯定会很方便.

  • `expect(response).to redirect_to(A_REGEX)`仅适用于Rails 4.对于Rails 3,你最好的选择可能是'expect(response.location).匹配(THE_REGEX)` (3认同)

Cad*_*ade 6

你能使用你的路线助手而不是普通的弦吗?如果是这样,您可以将哈希参数传递给路由助手,它们将被转换为查询字符串参数:

root_url foo: 'bar', baz: 'quux'
=> "http://www.your-root.com/?baz=quux&foo=bar"
expect(response).to redirect_to(root_url(foo: 'bar', baz: 'quux'))
Run Code Online (Sandbox Code Playgroud)

这有帮助,还是仅限于使用字符串而不是路由助手?

另一个想法是你可以直接断言params散列中的值而不是url +查询字符串,因为查询字符串params将序列化为params散列...


Ben*_*ing 6

我需要类似的东西,最后得到了这个:

能够编写测试而不用担心查询参数排序。

expect(response.location).to be_a_similar_url_to("http://example.com/?beta=gamma&alpha=delta")
Run Code Online (Sandbox Code Playgroud)

将以下内容放入 ./spec/support/matchers/be_a_similar_url_to.rb

RSpec::Matchers.define :be_a_similar_url_to do |expected|
  match do |actual|
    expected_uri = URI.parse(expected)
    actual_uri = URI.parse(actual)

    expect(actual_uri.host).to eql(expected_uri.host)
    expect(actual_uri.port).to eql(expected_uri.port)
    expect(actual_uri.scheme).to eql(expected_uri.scheme)
    expect(Rack::Utils.parse_nested_query(actual_uri.query)).to eql(Rack::Utils.parse_nested_query(expected_uri.query))
    expect(actual_uri.fragment).to eql(expected_uri.fragment)
  end

  # optional
  failure_message do |actual|
    "expected that #{actual} would be a similar URL to #{expected}"
  end

  # optional
  failure_message_when_negated do |actual|
    "expected that #{actual} would not be a similar URL to #{expected}"
  end
end
Run Code Online (Sandbox Code Playgroud)