2

I am a uploading image file on another site, and they have provided upload API for the same.

File upload process is divided into 2 parts

  1. Create image Id (POST)
  2. Upload image (PUT)

When I create an image id, it returns id in the response. For this, I have added following methods that achieves this functionality.

  def create_image_id
    response = create_via_api(data)
    # we get response in the following format
    # #<Net::HTTPCreated 201 Created readbody=true>
    find_id_from_response(response)
  end

  def create_via_api(data)
    access_token.post(IMAGE_CREATE_URL, data, 'Accept' => ACCEPT_HEADER)
  end

  # We are getting id from the response headers in the following format
  # location: SITE_URL/imageResources/5ac2acb2
  def find_id_from_response(response)
    id = response.to_hash['location'].first
    return unless id
    id.split('/').last.chomp
  end

Now I have to write the test case for the create_image_id method.

As for test case communicate with 3rd party API is not a good practice. So I am stubbing the POST response say,

  allow(Image).to receive(:find_id_from_response).and_return('1234')

so it will always return id as 123 so that I can write test case as

  expect(image. create_image_id).to eq 1234

As you can see find_id_from_response take parameter (#).

Note: here is the header of the response

  [36] pry(#)> response.to_hash
  {
  "content-type"=>["text/plain"],
  "x-frame-options"=>["SAMEORIGIN"],
  "location"=>["www.example.com/imageResources/cd87b8ef"],
  "vary"=>["Accept-Encoding"],
  "cache-control"=>["max-age=0, no-cache"],
  "pragma"=>["no-cache"],
  "date"=>["Tue, 15 Nov 2016 12:01:56 GMT"],
  "connection"=>["close"]
  }

I tried with following

  [28] pry()> Net::HTTPCreated.new(1, 201, 'Created')
  => #<Net::HTTPCreated 201 Created readbody=false>
  [29] pry()> a = Net::HTTPCreated.new(1, 201, 'Created')
  => #<Net::HTTPCreated 201 Created readbody=false>
  [30] pry()>)> a.to_hash
  => {}

it is returning empty hash. So how can I stub the response of create_via_api?

Let me know anything you need.

I-am-simple-user
  • 409
  • 7
  • 19

2 Answers2

1

I don't think there is an easy way return a http response object. So instead you could use a rspec mocks

response_hash = {
  "content-type"=>["text/plain"],
  "x-frame-options"=>["SAMEORIGIN"],
  "location"=>["www.example.com/imageResources/cd87b8ef"],
  "vary"=>["Accept-Encoding"],
  "cache-control"=>["max-age=0, no-cache"],
  "pragma"=>["no-cache"],
  "date"=>["Tue, 15 Nov 2016 12:01:56 GMT"],
  "connection"=>["close"]
}
response_double = double
allow(response_double).to receive(:to_hash).and_return(response_hash)
allow(instance).to receive(:create_via_api).and_return(response_double)
expect(instance.create_via_api("data").to_hash['content-type']).to eq(["text/plain"])

Another option is to use something that records and saves api calls for testing and uses the cached response for all subsequent test passes like vcr.

hajpoj
  • 13,299
  • 2
  • 46
  • 63
1

Try to use add_field (http://apidock.com/ruby/Net/HTTPHeader/add_field). It adds a value to a named header field, instead of replacing its value.

2.0.0-p643 :533 > response = Net::HTTPCreated.new('HTTP/2', 201, 'Created')
 => #<Net::HTTPCreated 201 Created readbody=false> 
2.0.0-p643 :534 > response.add_field('vary', 'Accept-Encoding')
 => ["Accept-Encoding"] 
2.0.0-p643 :535 >     response.add_field('cache-control', 'max-age=0, no-cache')
 => ["max-age=0, no-cache"] 
2.0.0-p643 :536 >     response.add_field('pragma', 'no-cache')
 => ["no-cache"] 
2.0.0-p643 :537 > response.to_hash
 => {"vary"=>["Accept-Encoding"], "cache-control"=>["max-age=0, no-cache"], "pragma"=>["no-cache"]} 
2.0.0-p643 :538 > 
shrikant1712
  • 4,336
  • 1
  • 24
  • 42