I'm working on a Rails application having a REST API in JSON format and versioned (according to this excellent Ryan's cast: http://railscasts.com/episodes/350-rest-api-versioning).
我正在开发一个Rails应用程序,它具有JSON格式的REST API并且版本化(根据这个优秀的Ryan演员:http://railscasts.com/episodes/350-rest-api-versioning)。
For instance, there is a spec/requests spec:
例如,有一个spec / requests规范:
require 'spec_helper'
describe "My Friends" do
describe "GET /my/friends.json" do
it "should get my_friends_path" do
get v1_my_friends_path, {}, {'HTTP_ACCEPT' => 'application/vnd.myapp+json; level=1'}
response.status.should be(401)
end
end
end
And it works well. But (keeping this example) how can we write the routing spec? For instance this spec isn't correct:
它运作良好。但是(保持这个例子)我们如何编写路由规范?例如,这个规范是不正确的:
require 'spec_helper'
describe "friends routing" do
it "routes to #index" do
get("/my/friends.json", nil, {'HTTP_ACCEPT' => 'application/vnd.myapp+json; level=1'}).
should route_to({ action: "index",
controller: "api/v1/private/my/friends",
format: "json" })
end
end
I tried different ways (such as request.headers['Accept']
and @request.headers['Accept']
, where request
is undefined and @request
is nil); I really don't see how to do.
我尝试了不同的方法(例如request.headers ['Accept']和@ request.headers ['Accept'],其中请求未定义且@request为nil);我真的不明白该怎么做。
I'm on Ruby 1.9.3, Rails 3.2.6 and rspec-rails 2.11.0. Thanks.
我使用的是Ruby 1.9.3,Rails 3.2.6和rspec-rails 2.11.0。谢谢。
13
By combining the ideas from Cristophe's and Piotr's answers, I came up with a solution that worked for me. I'm using rspec and rails 3.0.
通过结合Cristophe和Piotr的答案的想法,我想出了一个适合我的解决方案。我正在使用rspec和rails 3.0。
it 'should route like i want it to' do
Rack::MockRequest::DEFAULT_ENV["HTTP_ACCEPT"] = "*/*"
{get: "/foo/bar"}.
should route_to(
controller: 'foo',
action: 'bar',
)
Rack::MockRequest::DEFAULT_ENV.delete "HTTP_ACCEPT"
end
5
Currently you can't send addititional Headers in Routing specs, this is due to line 608
in actionpack-3.2.5/lib/action_dispatch/routing/route_set.rb
where it says:
目前你不能在路由规范中发送addititional Headers,这是由于actionpack-3.2.5 / lib / action_dispatch / routing / route_set.rb中的第608行所示:
env = Rack::MockRequest.env_for(path, {:method => method})
path
is your requested path "/my/friends.json"
and method is :get
The resulting env
contains something like the following:
path是您请求的路径“/my/friends.json”,方法是:get生成的env包含如下内容:
{
"rack.version"=>[1, 1],
"rack.input"=>#<StringIO:0xb908f5c>,
"rack.errors"=>#<StringIO:0xb908fac>,
"rack.multithread"=>true,
"rack.multiprocess"=>true,
"rack.run_once"=>false,
"REQUEST_METHOD"=>"GET",
"SERVER_NAME"=>"your-url.com", # if path was http://your-url.com/
"SERVER_PORT"=>"80",
"QUERY_STRING"=>"",
"PATH_INFO"=>"/",
"rack.url_scheme"=>"http",
"HTTPS"=>"off",
"SCRIPT_NAME"=>"",
"CONTENT_LENGTH"=>"0"
}
If you are able to mock Rack::MockRequest::env_for
it should be possible to inject other headers than the ones generated by env_for (see Hash above).
如果你能够模拟Rack :: MockRequest :: env_for,那么应该可以注入除env_for生成的头之外的其他头文件(参见上面的哈希)。
Other than that you are currently using the route_to matcher wrong, you should call it on a Hash where you specify the method and the path like this:
除了你当前正在使用route_to matcher错误之外,你应该在Hash上调用它,你可以在其中指定方法和路径,如下所示:
{ get: '/' }.should route_to(controller: 'main', action: 'index')
Let us know if you were able to Mock out that env_for and let it return your headers, would be nice to know.
如果您能够模拟出env_for并让它返回标题,请告诉我们。很高兴知道。
Regards Christoph
5
before do
ActionDispatch::TestRequest::DEFAULT_ENV["action_dispatch.request.accepts"] = "application/vnd.application-v1+json"
end
after do
ActionDispatch::TestRequest::DEFAULT_ENV.delete("action_dispatch.request.accepts")
end
2
You can using rspec's and_wrap_original
to mock the Rack::MockRequest.env_for
method:
您可以使用rspec的and_wrap_original来模拟Rack :: MockRequest.env_for方法:
expect(Rack::MockRequest).to receive(:env_for).and_wrap_original do |original_method, *args, &block|
original_method.call(*args, &block).tap { |hash| hash['HTTP_ACCEPT'] = 'application/vnd.myapp+json; level=1' }
end
0
For Rails 3 and 4 I had done the following in an RSpec around hook:
对于Rails 3和4,我在一个RSpec周围的钩子中完成了以下操作:
around do |example|
Rack::MockRequest::DEFAULT_ENV['HTTP_ACCEPT'] = 'application/vnd.vendor+json; version=1'
example.run
Rack::MockRequest::DEFAULT_ENV.delete 'HTTP_ACCEPT'
end
Since Rack >= 2.0.3
(used by Rails 5) the Rack::MockRequest::DEFAULT_ENV
hash is frozen.
由于Rack> = 2.0.3(由Rails 5使用),Rack :: MockRequest :: DEFAULT_ENV哈希被冻结。
You can redefine the constant and use Kernel.silence_warnings to silence the Ruby warnings:
您可以重新定义常量并使用Kernel.silence_warnings来消除Ruby警告:
around do |example|
silence_warnings do
Rack::MockRequest::DEFAULT_ENV = Rack::MockRequest::DEFAULT_ENV.dup
end
Rack::MockRequest::DEFAULT_ENV['HTTP_ACCEPT'] = 'application/vnd.vendor+json; version=1'
example.run
Rack::MockRequest::DEFAULT_ENV.delete 'HTTP_ACCEPT'
end
It's a bit of hack but it works like a charm.
这有点像黑客,但它就像一个魅力。
本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.silva-art.net/blog/2012/07/11/b9f89f4e9351c6d1dbf0b2d9b551b330.html。