How can you universally override the get and post methods in RSpec?

限于喜欢 提交于 2019-12-24 00:55:26

问题


I'd like to override the get and post methods in RSpec.

I want to do this in order to deal with subdomains in my tests. As far as I can tell, the only way to deal with subdomains is to alter the @request object before each call. I could do this before each and every test but that's going to lead to some really messy code.

In an effort to keep things DRY I've tried using a config.before(:each) method in spec_helper.rb however this doesn't seem to be run in the same scope as the test and doesn't have access to @request.

My next bsest approach is therefore to overrride get and post which are in the correct scope.

def get *args
  @request.host = @required_domain if @required_domain
  super *args
end

I can include this code in the top of each spec file but I'd rather set it universally. If I set it in spec_helper.rb though it does not get called.

Where can I set this to override the default get method?


回答1:


however this doesn't seem to be run in the same scope as the test.

That's not quite right - it's run in the same scope, but before @request is configured, so it has no effect.

Try this:

module RequestExtensions
  def get(*)
    @request.host = @required_domain if @required_domain
    super
  end
end

RSpec.configure do |c|
  c.include RequestExtensions, :type => :controller
end

HTH, David




回答2:


I just ran into an issue which routed me to this question. The accepted solution guided me to the more effective implementation as of rack-test 0.6.3.

I manually created ./spec/helpers/rspec_http_request_override_helper.rb

module RspecHttpRequestsOverrideHelper

  def get(uri, params = {}, env = {}, &block)
    super(uri, params, set_json_headers(env), &block)
  end

  def post(uri, params = {}, env = {}, &block)
    super(uri, convert_to_json(params), set_json_headers(env), &block)
  end

  def put(uri, params = {}, env = {}, &block)
    super(uri, convert_to_json(params), set_json_headers(env), &block)
  end

  def delete(uri, params = {}, env = {}, &block)
    super(uri, convert_to_json(params), set_json_headers(env), &block)
  end

  # override other HTTP methods if necessary

  private

  def set_json_headers(env={})
    env.merge({'ACCEPT' => "application/json", 'CONTENT_TYPE' => 'application/json'}) unless env.nil?
  end

  def convert_to_json(params={})
    params.to_json unless params.nil?
  end

end

Then I added the below to my spec_helper.rb

# require assuming project root is loaded into ruby's class paths
require './spec/helpers/rspec_http_request_override_helper'
RSpec.configure do |config|
  config.include RspecHttpRequestsOverrideHelper

  # Other settings
end

And that was it!

Note: The get method above doesn't convert the params value to json intentionally. Param values are encoded into the query string and then sent. Not as part of the HTTP body in the request, even though the GET http method supports sending a body; see here for more details.

My issue was that the rspec test helpers for an API I am building were converting boolean types to string types when sending the request to the API. Turns out when you don't specify a content-type header for json the data is passed as multipart/form-data or x-www-form-urlencoded depending on the HTTP method; see here for more details. This was converting my special data types, which are valid in json like integers and booleans, into strings. And effectively needing me to convert them on the API's end. It wasn't until I added validation for the input into my API that this was exposed. Yay for validations and tests!

Now, I needed to effectively apply a content-type header to all my requests and convert the params to json when sending the requests; I was calling the http methods with the params value being a ruby hash. I have over 200 tests so going in an manually changing them all would not have been an optimal solution. So I implemented the below solution. Which works very well.

I decided to follow the same method definition as rack-test was and then I could effectively call super after editing the requests.

My failing tests now started passing and my previous tests where none the wiser.

Hopefully this helps others who run into a similar issue.




回答3:


The question betrays incorrect assumptions. You shouldn't be writing controller specs in the first place. This should all be done with Cucumber -- and in that case, you can just specify particular URLs, so the problem goes away.



来源:https://stackoverflow.com/questions/8447944/how-can-you-universally-override-the-get-and-post-methods-in-rspec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!