Stubbing RestClient response in RSpec
Asked Answered
T

3

12

I have the following spec...

  describe "successful POST on /user/create" do
    it "should redirect to dashboard" do
      post '/user/create', {
          :name => "dave",
          :email => "[email protected]",
          :password => "another_pass"
      }
      last_response.should be_redirect
      follow_redirect!
      last_request.url.should == 'http://example.org/dave/dashboard'
    end
  end

The post method on the Sinatra application makes a call to an external service using rest-client. I need to somehow stub the rest client call to send back canned responses so I don't have to invoke an actual HTTP call.

My application code is...

  post '/user/create' do
    user_name = params[:name]
    response = RestClient.post('http://localhost:1885/api/users/', params.to_json, :content_type => :json, :accept => :json)
    if response.code == 200
      redirect to "/#{user_name}/dashboard"
    else
      raise response.to_s
    end
  end

Can someone tell me how I do this with RSpec? I've Googled around and come across many blog posts which scratch the surface but I can't actually find the answer. I'm pretty new to RSpec period.

Thanks

Tillis answered 10/1, 2013 at 21:14 Comment(0)
H
18

Using a mock for the response you can do this. I'm still pretty new to rspec and test in general, but this worked for me.

describe "successful POST on /user/create" do
  it "should redirect to dashboard" do
    RestClient = double
    response = double
    response.stub(:code) { 200 }
    RestClient.stub(:post) { response }

    post '/user/create', {
      :name => "dave",
      :email => "[email protected]",
      :password => "another_pass"
    }
    last_response.should be_redirect
    follow_redirect!
    last_request.url.should == 'http://example.org/dave/dashboard'
  end
end
Hermosillo answered 10/1, 2013 at 22:17 Comment(3)
I'd suggest moving the double set up into a let block, and the post into a before block`.Congelation
Thanks for the suggestion @iain but not related at all to the question :) But yes, it should have a describe 'POST on /user/create' block with a let(:sucessful_response) {...} and the before block and then a describe for sucessful and error response.Hermosillo
Thanks guys. I'd rather use this solution with the tools I already have rather than turn to a third party and this works well.Tillis
O
7

Instance doubles are the way to go. If you stub a method that doesn't exist you get an error, which prevents you from calling an un-existing method in production code.

      response = instance_double(RestClient::Response,
                                 body: {
                                   'isAvailable' => true,
                                   'imageAvailable' => false,
                                 }.to_json)
      # or :get, :post, :etc
      allow(RestClient::Request).to receive(:execute).and_return(response)
Obtuse answered 11/4, 2019 at 1:58 Comment(0)
S
3

I would consider using a gem for a task like this.

Two of the most popular are WebMock and VCR.

Scrophulariaceous answered 10/1, 2013 at 22:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.