Search code examples
ruby-on-railsrspecrest-clientwebmock

Rails webmock stubbing out localhost api call


I have a controller, which has a post_review action which calls a Rest Client API call.

def post_review
  ...
  headers = { "CONTENT_TYPE" => "application/json",
              "X_AUTH_SIG" => Rails.application.secrets[:platform_receiver_url][:token] }
  rest_client.execute(:method => :put,
                      :url => Rails.application.secrets[:platform_receiver_url][:base_url] + response_body["application_id"].to_s,
                      :content_type => :json,
                      :payload => response_body.to_json,
                      :headers => headers)
  document_manual_result(response_body)
  delete_relavent_review_queue(params[:review_queue_id])
  ...
end

The document_manual_result is a logging method and the delete_relavent_review_queue is a callback type method which will delete the item.

I have written several tests that are testing the side effects of the post_review action, namely that it documents that I have sent off the result(aka:response_body) and that I delete another object.

  describe "Approved#When manual decision is made" do
    it "should delete the review queue object" do
      e = Event.create!(application_id: @review_queue_application.id)
      login_user @account
      post :post_review, @params
      expect{ReviewQueueApplication.find(@review_queue_application.id)}.to raise_exception(ActiveRecord::RecordNotFound)
    end

    it "should update the event created for the application" do
      e = Event.create!(application_id: @review_queue_application.id)
      login_user @account
      post :post_review, @params
      expect(Event.find(e.id).manual_result).to eq(@manual_result)
    end
  end

Before I turned on RestClient the tests worked, but now that rest client is executing It is breaking the specs. I would like to stub just the rest_client.execute portion of the controller action, so I can test the other side effects of the method. The URL I have it pointing to is localhost:3001 so I tried:

 stub_request(:any, "localhost:3001") 

I used it within, my before block which didn't do anything and I tried it inside the actual test it block just before I post :post_review, @params and Webmock seems to be doing nothing. What I thought webmock does, is that it is listening to any requests being made to a specific URL and it returns a success by default or a block of options that you specify. I am not sure I am using this correctly.


Solution

  • In this snippet:

    stub_request(:any, "localhost:3001") 
    

    :any refers to the http method to call like GET or POST. So you are stubbing GET/POST/whatever on exactly that URL and only that URL. My guess is that what you are sending requests to is not exactly localhost:3001.

    Try extracting Rails.application.secrets[:platform_receiver_url][:base_url] + response_body["application_id"].to_s out into a variable and log it when you run your specs. My guess is you'll need to change your stub to be that URL which is likely something like localhost:3001/some_resource/1.

    To Stub all paths on localhost:3001

    Webmock also supports matching urls by regex:

    stub_request(:any, /localhost:3001*/)