EzDevInfo.com

webmock

Library for stubbing and setting expectations on HTTP requests in Ruby.

How to use webmock regex matcher?

How to match a URL like:

http://www.example.com/foo/:id/bar
http://www.example.com/foo/1/bar
http://www.example.com/foo/999/bar

stub_request(:post, "www.example.com")


Source: (StackOverflow)

One Test Case Seems to Interfere the Other Test Case

This is on Rails 4.0.11. I am writing a test using minitest and webmock for a worker that interacts with an API. I have two test cases (so far) in my test file. When I run both tests, the second one (the one with "success" in the title) fails. When I comment out the passing test (the one with "retry" in the title), the test case that was failing passes. It seems like the test cases are interfering with each other, but I don't see how.

(I've obfuscated company confidential data in these code examples. Hi boss!)

Here's the test:

require 'test_helper'

class FoocorpCheckStatusWorkerTest < ActiveSupport::TestCase

  REQUEST_HEADERS = {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'text/xml', 'User-Agent'=>'Ruby'}
  EXPECTED_BODY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<POSBizServices xmlns=\"http://api.foocorp.com\">\n  <POSBizServiceHeader>\n    <userId>ABC</userId>\n    <password>abc123</password>\n    <clientId>123</clientId>\n    <action>CHECKSTATUS</action>\n    <responseFormat>XML</responseFormat>\n  </POSBizServiceHeader>\n  <request>\n    <checkStatus>\n      <ecpdId>123</ecpdId>\n      <refNum>12345678</refNum>\n    </checkStatus>\n  </request>\n</POSBizServices>\n"

  def sample_response_body(order_level_status_code: '', line_level_status_code: '')

    return <<-SAMPLE_RESPONSE_BODY
      <?xml version="1.0" encoding="UTF-8"?>
      <POSBizServices xmlns="http://api.foocorp.com">
        <POSBizServiceHeader>
          <userId>ABC</userId>
          <password>abc123</password>
          <clientId>123</clientId>
          <statusCode>#{order_level_status_code}</statusCode>
          <statusDescription>2015-01-29 14:03:07 [QA13:MS_WSQA4_ONEPOS_01:01] : Request Processed Successfully</statusDescription>
          <action>CHECKSTATUS</action>
          <responseFormat>XML</responseFormat>
        </POSBizServiceHeader>
        <response>
          <statusResponse>
            <count>1</count>
            <orderStatus>
              <orderId>12345678</orderId>
              <orderDate>01/27/2015</orderDate>
              <stats>1,0</stats>
              <aceOrderNo></aceOrderNo>
              <locationCode></locationCode>
              <lineInfoList>
                <count>1</count>
                <lineStatus>
                  <lineSeq>1</lineSeq>
                  <statusCode>#{line_level_status_code}</statusCode>
                  <statusDesc>No Status Yet.</statusDesc>
                </lineStatus>
              </lineInfoList>
            </orderStatus>
          </statusResponse>
        </response>
      </POSBizServices>
    SAMPLE_RESPONSE_BODY
  end

  test "retry codes leave activity processor step in waiting state and activity in auto_processing state" do

    activity_processor_step = activity_processor_steps(:vip_vm_password_reset_step)
    activity = activity_processor_step.activity

    FoocorpVipCheckStatusWorker::STATUS_CODE_MATRIX[:retry].each do |status_code_pair|

      stub_request(:post, FOOCORP_VIP_CONFIG[:base_url]).
        with(:body => /^.*$/,
             :headers => REQUEST_HEADERS
            ).
            to_return(:status => 200, :body => sample_response_body(order_level_status_code: status_code_pair.first, line_level_status_code: status_code_pair.last), :headers => {})

      FoocorpVipCheckStatusWorker.new.perform

      activity.reload
      assert_equal("auto_processing", activity.state)

      activity_processor_step.reload
      assert_equal("waiting", activity_processor_step.state)

    end
  end

  test "success codes complete activity and activity processor step" do

    activity_processor_step = activity_processor_steps(:vip_vm_password_reset_step)
    activity = activity_processor_step.activity

    FoocorpVipCheckStatusWorker::STATUS_CODE_MATRIX[:success].each do |status_code_pair|

      stub_request(:post, FOOCORP_VIP_CONFIG[:base_url]).
        with(:body => /^.*$/,
             :headers => REQUEST_HEADERS
            ).
            to_return(:status => 200, :body => sample_response_body(order_level_status_code: status_code_pair.first, line_level_status_code: status_code_pair.last), :headers => {})

      FoocorpVipCheckStatusWorker.new.perform

      activity.reload
      assert_equal("completed", activity.state)

      activity_processor_step.reload
      assert_equal("completed", activity_processor_step.state)
    end
  end
end

Here's the worker:

class FoocorpVipCheckStatusWorker
  @queue = :short_running

  # Foocorp VIP returns an order-level status code and description
  # and a line-level status code and description. The comments describing
  # the status codes in STATUS_CODE_MATRIX are from Foocorp's Docs.
  #
  # Array format for status codes is:
  # ["(order-level status code)", "(line-level status code)"]

  STATUS_CODE_MATRIX = {
    :success  => [
      ["00057", "00051"]  # Request Processed Successfully
    ],
    :retry    => [
      ["00057", "00053"], # No Status Yet
      ["00057", "00054"], # Order processed successfully but activation is pending.
      ["00099", ""],      # Unexpected error occurred during processing e.g. null pointer exception which causes thread to terminate.
      ["00059", ""],      # Server time out occurred.
      ["10009", ""],      # Back End call returned invalid agent data.
      ["10010", ""],      # Application fails to load ECPD profile details.
      ["00058", "10013"], # Backend calls fails to load Billing information for account. It may be due to some internal issue.
      ["00058", "10032"], # Exception occurred in Bulk Service write
      ["00058", "10033"], # Error occurred in Bulk Service write for reassign
      ["00058", "10040"], # Sub Account create failed
      ["00058", "10144"]  # UNABLE TO RETRIEVE CREDIT INFORMATION
    ]
  }

  def perform

    ActivityProcessorStep.where(state: "waiting").where("vip_ref_num IS NOT NULL").each do |activity_processor_step|

      client = Remote::Clients::FoocorpVipClient.new(
        :params   => {
          :ecpd_id     => activity_processor_step.activity.carrier_account.parent_account.api_access_id,
          :vip_ref_num => activity_processor_step.vip_ref_num
        }
      )
      response = client.check_status
      #TODO: Remove debugging code
      #binding.pry
      order_status_code = response.first[:order_status_code]
      order_status_desc = response.first[:order_status_desc]
      line_status_code  = response.last[:line_status_code]
      line_status_desc  = response.last[:line_status_desc]

      status_codes      = [order_status_code, line_status_code]
      response_message  = line_status_desc.present? ? line_status_desc : order_status_desc
      response_message  ||= "No status description given"

      success             = STATUS_CODE_MATRIX[:success].detect{ |codes_array| codes_array == [order_status_code, line_status_code]}.present?
      retry_status_check  = STATUS_CODE_MATRIX[:retry].detect{ |codes_array| codes_array == [order_status_code, line_status_code]}.present?
      stale_request       = retry_status_check && Time.now > (activity_processor_step.created_at + activity_processor_step.days_to_expire.days)

      if success
        activity_processor_step.update_activity_status('Complete', nil, nil, response_message)
      elsif stale_request
        activity_processor_step.update_activity_status('Failure', nil, nil, "Activity processor step expired.")
      elsif !retry_status_check
        activity_processor_step.update_activity_status('Failure', nil, nil, response_message)
      end

    end
  end
end

Here's my terminal output:

Running both test cases:

me@domo-kun ~/my-project (feature_foocorp_check_status_worker=)$ be rake test TEST=test/workers/foocorp_check_status_worker_test.rb 
Run options: --seed 58882

# Running tests:

.F

Fabulous tests in 2.009658s, 0.9952 tests/s, 11.4447 assertions/s.

  1) Failure:
FoocorpCheckStatusWorkerTest#test_success_codes_complete_activity_and_activity_processor_step     [/Users/steven/Development/my-company/my_company/test/workers/foocorp_check_status_worker_test.rb:86]:
Expected: "completed"
  Actual: "auto_processing"

2 tests, 23 assertions, 1 failures, 0 errors, 0 skips

Commenting out the first ("retry") test case:

me@domo-kun ~/my-project (feature_foocorp_check_status_worker=)$ be rake test TEST=test/workers/foocorp_check_status_worker_test.rb 
Run options: --seed 14937

# Running tests:

.

Fabulous tests in 3.474386s, 0.2878 tests/s, 0.5756 assertions/s.

1 tests, 2 assertions, 0 failures, 0 errors, 0 skips

When I run both tests together and use binding.pry (commented out here) in the worker to examine the value of response during the "success" test case (the one that fails), I get the following two results. I expect the same result (the second one) in both cases.

Running both test cases:

[1] pry(#<VerizonVipCheckStatusWorker>)> response
=> [{:order_status_code=>"00057",
  :order_status_desc=>"",
  :_summary=>{:order_status_code=>"00057", :order_status_desc=>""}},
 {:line_status_code=>"00053",
  :line_status_desc=>"No Status Yet.",
  :_summary=>{}}]

Commenting out the first ("retry") test case:

[2] pry(#<VerizonVipCheckStatusWorker>)> response
=> [{:order_status_code=>"00057",
  :order_status_desc=>"",
  :_summary=>{:order_status_code=>"00057", :order_status_desc=>""}},
 {:line_status_code=>"00051",
  :line_status_desc=>"No Status Yet.",
  :_summary=>{}}]

The value of response in that last example is what I would expect it to be during the first iteration of the "retry" test case, not during the "success" case.

I've tried moving what was in a setup method into the constants and sample_response_body method you see here. I also tried adding this teardown method, but it didn't help:

def teardown
  WebMock.reset!
end

I'm writing both the worker and the test from scratch, so it's entirely possible that I have a dumb syntax/logic errors somewhere. I apologize for what is probably an overly verbose question, but this really has me tearing my hair out. Your help is appreciated. Thanks.


Source: (StackOverflow)

Advertisements

Ruby TestUnit, VCR and HTTP API Requests

I am building an API wrapper and am writing some tests for it and I have a couple of questions.

1) How do I write an assert for calls where data doesn't exist? For example, looking up a member by id using the API but the user won't exist yet.
2) How do I write an assert for testing PUT and DELETE requests?

I already have a grasp on testing GET and POST requests just not sure on the other 2 verbs.


Source: (StackOverflow)

Using specific VCR cassette based on request

Situation: testing a rails application using Rspec, FactoryGirl and VCR.

Every time a User is created, an associated Stripe customer is created through Stripe's API. While testing, it doesn't really makes sense to add a VCR.use_cassette or describe "...", vcr: {cassette_name: 'stripe-customer'} do ... to every spec where User creation is involved. My actual solution is the following:

RSpec.configure do |config|
  config.around do |example|
    VCR.use_cassette('stripe-customer') do |cassette|
      example.run
    end
  end
end

But this isn't sustainable because the same cassette will be used for every http request, which of course is very bad.

Question: How can I use specific fixtures (cassettes) based on individual request, without specifying the cassette for every spec?

I have something like this in mind, pseudo-code:

stub_request(:post, "api.stripe.com/customers").with(File.read("cassettes/stripe-customer"))

Relevant pieces of code (as a gist):

# user_observer.rb

class UserObserver < ActiveRecord::Observer

  def after_create(user)
    user.create_profile!

    begin
      customer =  Stripe::Customer.create(
        email: user.email,
        plan: 'default'
        )

      user.stripe_customer_id = customer.id
      user.save!
    rescue Stripe::InvalidRequestError => e
      raise e
    end

  end
end


# vcr.rb

require 'vcr'

VCR.configure do |config|
  config.default_cassette_options = { record: :once, re_record_interval: 1.day }
  config.cassette_library_dir = 'spec/fixtures/cassettes'
  config.hook_into :webmock
  config.configure_rspec_metadata!
end


# user_spec.rb

describe :InstanceMethods do
  let(:user) { FactoryGirl.create(:user) }

  describe "#flexible_name" do
    it "returns the name when name is specified" do
      user.profile.first_name = "Foo"
      user.profile.last_name = "Bar"

      user.flexible_name.should eq("Foo Bar")
    end
  end
end

Edit

I ended doing something like this:

VCR.configure do |vcr|
  vcr.around_http_request do |request|

    if request.uri =~ /api.stripe.com/
      uri = URI(request.uri)
      name = "#{[uri.host, uri.path, request.method].join('/')}"
      VCR.use_cassette(name, &request)

    elsif request.uri =~ /twitter.com/
      VCR.use_cassette('twitter', &request)
    else
    end

  end
end

Source: (StackOverflow)

How can I test a Ruby command-line program that communicates with a web service?

I am building a Ruby command-line program that communicates with a web service. I am using Cucumber and Aruba to test the program. The problem is that I need to control the data returned from the web service; the program grabs a stream of user comments, so this can change frequently as new comments are added. I tried to mock the web service using WebMock, but this didn't work, since Aruba spins the command-line program off into a separate process that is unaffected by WebMock (so it still communicated with the real web service).

How can I test the output of this program using Cucumber?


Edit: The web service returns the stream as JSON data. I've captured a snapshot of data to use for testing; in a nutshell, I'm looking for a way to substitute my static data in place of an actual call to the web service.

Or, if there's a completely different way to accomplish this goal, I'm all ears.


Source: (StackOverflow)

WebMock simulate failing API (no internet, timeout ++)

I am trying to simulate unexpected behaviour from a web api, such as not finding the server and timeouts, using webmock.

What would be the best way to do this? All I can think of is to do something like this:

stubbed_request = stub_request(:get, "#{host}/api/something.json").
with(:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json', 'User-Agent'=>'Ruby'}).
to_return(:status => [500, "Internal Server Error"])

That should work for things like 404 etc., but how can I test timeouts, server not found/offline server, and no internet connection?


Source: (StackOverflow)

How to use WebMock to mock Paperclip call in a Sinatra app?

This code works fine without WebMock.

Raising an exception:

Paperclip::AdapterRegistry::NoHandlerError:
   No handler found for #<URI::HTTP:0x007ff3852cefb8 URL:http://www.example.com/images/foo.jpg>
# ./spec/support/api_mock.rb:34:in `process_image_for'

Test:

let( :image_url  ) { 'http://www.example.com/images/foo.jpg'  }
...
stub_request(:post, image_url)
  .to_return(:status => 200, :body => File.read('spec/fixtures/image.jpg'), :headers => {})
...hit Sinatra app...

api_mock.rb:

def self.process_image_for suggestion, params
  if params[:image]
    suggestion.image = URI.parse( params[:image] )  # line 34
    suggestion.save!
  end
end

Source: (StackOverflow)

Test oauth2 get_token with rspec

I'm creating a controller spec for the get_token part of an oauth2 authentication. At this point the user has authorized my app and I need to generate and save the token and other information. Rspec fails with a somewhat cryptic error.

Failure/Error: get :auth, { code: "auth_code", scope: "read_write" }
     OAuth2::Error:
       {:token_type=>"bearer", 
        :stripe_publishable_key=>"PUBLISHABLE_KEY", 
        :scope=>"read_write", 
        :livemode=>"false", 
        :stripe_user_id=>"USER_ID",  
        :refresh_token=>"REFRESH_TOKEN", 
        :access_token=>"ACCESS_TOKEN"}

Here's the controller code. Rspec says it fails on get_token.

require 'oauth2'

def auth
  code = params[:code]
  client = oauth_client
  token_response = client.auth_code.get_token(code, params: { scope: 'read_write' })
  token = token_response.token

And here's the test. The webmock should be intercepting get_token. It is the autogenerated webmock suggeted by rspec that I filled in the body with the appropriate request and response body.

before do
  stub_request(:post, "https://connect.stripe.com/oauth/token").
    with(:body => {"client_id"=>"CLIENT_ID",
                   "client_secret"=>"SOME_SECRET",
                   "code"=>"auth_code",
                   "grant_type"=>"authorization_code",
                   "params"=>{"scope"=>"read_write"}},
         :headers => {'Accept'=>'*/*',
                      'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
                      'Content-Type'=>'application/x-www-form-urlencoded',
                      'User-Agent'=>'Faraday v0.9.0'}).
    to_return(:status => 200,
              :body => {token_type: "bearer",
                        stripe_publishable_key: "PUBLISHABLE_KEY",
                        scope: "read_write",
                        livemode: "false",
                        stripe_user_id: "USER_ID",
                        refresh_token: "REFRESH_TOKEN",
                        access_token: "ACCESS_TOKEN"},
              :headers => {})
end

describe "#auth" do
  it "creates a payment gateway" do
    get :auth, { code: "auth_code", scope: "read_write" 
  end
end

This process already works in practice so at least the controller code is not to blame. What am I doing wrong?


Source: (StackOverflow)

Having trouble with WebMock, not stubbing correctly

Ruby 1.9.3, RSpec 2.13.0, WebMock 1.17.4, Rails 3

I am writing tests for a company app. The controller in question displays a table of a customer's placed calls, and allows for sort/filter options.

EDIT The test fails because with my current setup, the path does not render, because the recorder_server is either not running locally, OR not setup correctly. Please help with this, too.

A Errno::ECONNREFUSED occurred in recordings#index:
Connection refused - connect(2)
/usr/local/lib/ruby/1.9.1/net/http.rb:763:in `initialize'

-------------------------------
Request:
-------------------------------
* URL       : http://www.recorder.example.com:8080/recorded_calls
* IP address: 127.0.0.1
* Parameters: {"controller"=>"recordings", "action"=>"index"}
* Rails root: /var/www/rails/<repository>
  1. As a call is placed, its data joins an xml file, created by an external API, called Recorder
  2. The RecordingsController takes the xml file, and parses it into a hash.
  3. When you visit the associated path, you see the results of the hash -- a table of placed calls, their attributes, and parameters for sort/filter.

Here is my spec so far.

require 'spec_helper'
include Helpers

feature 'Exercise recordings controller' do
  include_context "shared admin context"

  background do
    canned_xml = File.open("spec/support/assets/canned_response.xml").read
    stub_request(:post, "http://recorder.example.com:8080/recorder/index").
      with(body: {"durations"=>["1"], "durations_greater_less"=>["gt"], "filter_from_day"=>"29", "filter_from_hour"=>"0", "filter_from_minute"=>"0", "filter_from_month"=>"12", "filter_from_year"=>"2014", "filter_prefix"=>true, "filter_to_day"=>"29", "filter_to_hour"=>"23", "filter_to_minute"=>"59", "filter_to_month"=>"12", "filter_to_year"=>"2014"}, # "shared_session_id"=>"19f9a08807cc70c1bf41885956695bde"},
           headers: {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Ruby'}).
      to_return(status: 200, body: canned_xml, headers: {})
    uri = URI.parse("http://recorder.example.com:8080/recorder/index")
    visit recorded_calls_path
  end

  scenario 'show index page with 1 xml result' do
    #page.save_and_open_page
    expect(title).to eq("Recorded Calls")
  end
end

And here is the RecordingsController

class RecordingsController < ApplicationController
  # before_filter options
  def index
    test_session_id = request.session_options[:id]
    #Make request to recording app for xml of files
    uri = URI.parse("http://#{Rails.application.config.recorder_server}:#{Rails.application.config.recorder_server_port}/recorder/index")
    http = Net::HTTP.new(uri.host, uri.port)
    xml_request = Net::HTTP::Post.new(uri.request_uri)
    xml_request_data = Hash.new
    # sorting params
    xml_request_data[:shared_session_id] = request.session_options[:id]
    xml_request.set_form_data(xml_request_data)
    response = http.request(xml_request)
    if response.class == Net::HTTPOK
      @recordings_xml = XmlSimple.xml_in(response.body)
      @recordings_sorted = @recordings_xml["Recording"].sort { |a,b| Time.parse("#{a["date"]} #{a["time"]}") <=> Time.parse("#{b["date"]} #{b["time"]}") } unless @recordings_xml["Recording"].nil?
    else @recordings_xml = Hash.new
    end
  end
  # other defs
end

Any and all advice is much appreciated. Thank you.


Source: (StackOverflow)

Webmock not responding to stub request with query

I'm working on a Ruby on Rails gem and I'm trying webmock because I need to interact (and test) an external API not under my control.

So, here is the snippet which is in before(:each) because I was stubbing it there:

before do
  uri = URI.join(client.class.base_uri, DataComApi::ApiURI.search_contact).to_s
  stub_request(
    :get,
    uri
  ).with(
    query: hash_including({
      'pageSize' => 0,
      'offset'   => 0
    })
  ).to_return(
    body: FactoryGirl.build(
      :data_com_search_contact_response,
      totalHits: 0
    ).to_json
  )
  # DEBUG
  require 'httparty'
  HTTParty.get(
    uri,
    {
      query: {
        offset:   0,
        pageSize: 0
      }
    }
  )
end

And here you can see the console output of rspec command:

  3) DataComApi::Client#search_contact returns instance of SearchContact
     Failure/Error: HTTParty.get(
     WebMock::NetConnectNotAllowedError:
       Real HTTP connections are disabled. Unregistered request: GET https://www.jigsaw.com/rest/searchContact.json?offset=0&pageSize=0

       You can stub this request with the following snippet:

       stub_request(:get, "https://www.jigsaw.com/rest/searchContact.json?offset=0&pageSize=0").
         to_return(:status => 200, :body => "", :headers => {})

       registered request stubs:

       stub_request(:get, "https://www.jigsaw.com/rest/searchContact.json with query params hash_including({"offset"=>0, "pageSize"=>0})")

       ============================================================
     # ./spec/models/client_spec.rb:65:in `block (3 levels) in <top (r

If I remove the :query key both on HTTParty.get and in stub_request, it works, but I need those query keys and values to test the API.

I tested even by replacing in stub_request, uri with /searchContact.json/ but had same issue.

Here you can find a GIST


Source: (StackOverflow)

Webmock: how to fake a gzipped response?

I don't have much experience with stubbing and am having issues with requests to Braintree using webmock and braintree-rails.

spec/spec_helper.rb

RSpec.configure do |config|
  config.include(ConnectionHelper)

  config.before(:each) do
    stub_request(:post, /.*braintree.*/).
    with(braintree_hash).to_return(gzipped_response)
  end
end

spec/support/connection_helper.rb

def gzipped_response
  {
    status: 200,
    body: "\u001F\x8B\b\0:\x87GU\0\u0003\u0003\0\0\0\0\0\0\0\0\0",
    headers: {}
  } 
end

def braintree_hash
  { :body => /.*/,
    :headers => {'Accept'=>'application/xml', 'Content-Type'=>'application/xml',
    'User-Agent'=>'Braintree Ruby Gem 2.42.0 (braintree-rails-1.4.0)',
    'X-Apiversion'=>'4'}
  }
end

Rspec error:

2) Content: when ordering content show page has relevant information 
     Failure/Error: click_button "Order"
     Braintree::UnexpectedError:
       expected a gzipped response
     # ./app/classes/payment.rb:13:in `generate_token'
     # ./app/controllers/posts_controller.rb:44:in `pay'
     # ./spec/features/content_spec.rb:251:in `block (4 levels) in <top (required)>'

I'm trying to test the page, not the payments themselves, however when rendering the page a token needs to be retrieved first and so I'm getting this error.

How would I go about faking a gzipped response, or alternatively skip anything to do with Braintree requests in my tests?

app/controllers/posts_controller.rb

def pay
  @post = Post.find(params[:id])
  @client_token = Payment.new(current_user).generate_token
end

app/classes/payment.rb

class Payment    
  def initialize(customer)
    @customer = customer
    @customer_id = @customer.id
  end

  def generate_token
    Braintree::ClientToken.generate(customer_id: @customer_id)
  end   
end

Source: (StackOverflow)

What is the purpose of stubbing an HTTP request (e.g. using the WebMock gem)?

As a precursor FYI, I'm a budding developer. I'm trying to write a test for an http POST method for a Ruby gem. From what I can understand, when you stub an http response, for instance with the Ruby WebMock gem, you're basically telling it what to post and then artificially telling it what to respond with. For example, here is the code I'm trying to test:

## githubrepo.rb

module Githubrepo

include HTTParty

def self.create(attributes)

  post = HTTParty.post(
      'https://api.github.com/user/repos',

      :headers => {
        'User-Agent' => 'Githubrepo',
        'Content-Type' => 'application/json',
        'Accept' => 'application/json'
      },

      :basic_auth => {
          :username => attributes[:username],
          :password => attributes[:password]
      },

      :body => {
          'name' => attributes[:repository],
          'description' => attributes[:description]
      }.to_json
  )

Githubrepo.parse_response_from(post, attributes[:wants_ssh])

end

My RSpec test fails when I write:

Githubrepo.create(:repository => 'test', :username => 'test_user', :password => '1234')

because it makes a real HTTP request. It recommends I do the following instead:

        stub_request(:post, "https://test_user:test_password@api.github.com/user/repos").
                with(:body => "{\"name\":\"test_repo\",\"description\":null}",
                     :headers => {'Accept'=>'application/json', 'Content-Type'=>'application/json', 'User-Agent'=>'Githubrepo'}).
           to_return(:status => 200, :body => "", :headers => {})

But to me, this seems like it's pointless since it's basically telling what to send and what to respond with. I can edit the URL to say "https://bananas@git-banana.banana" and the header to say Content-type => 'Rumplestilskin' and RSpec is ok with that. How am I supposed to integrate this into testing the functionality of the create method I specified above? Or if anything, can somebody point me to a solid beginner guide or blog to help me with this question? The Ruby gem READMEs seem to assume the user knows a thing or two already about this and I don't.


Source: (StackOverflow)

Stub multipart requests with webmock/rspec

I have been trying for a while to stub multipart requests using webmock and have not found a satisfying solution.

Ideally, I would like to stub the request as follow:

stub_request(:post, 'http://test.api.com').with(:body => { :file1 => File.new('filepath1'), file2 => File.new('filepath2') })

However, this does not seem to work and RSpec complains that the request has not been stubbed. The non-stubbed request is printed:

stub_request(:post, "http://test.api.com").
     with(:body => "--785340\r\nContent-Disposition: form-data; name=\"file1\"; filename=\"filepath1\"\r\nContent-Type: text/plain\r\n\r\nhello\r\n--785340\r\nContent-Disposition: form-data; name=\"file2\"; filename=\"filepath2\"\r\nContent-Type: text/plain\r\n\r\nhello2\r\n--785340\r\n",
          :headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Content-Length'=>'664', 'Content-Type'=>'multipart/form-data; boundary=785340', 'User-Agent'=>'Ruby'}).
     to_return(:status => 200, :body => "", :headers => {})

Of course, I can't really follow this suggestion because the boundaries are generated dynamically. Any idea how I could properly stub these requests?

Thanks! Bruno


Source: (StackOverflow)

Test response of Rails 3 background job (API-Request) with VCR in Cucumber feature

I have a Rails 3 background job (delayed_job) which sends a hipchat / Campfire message to their API and I want to check the response in my Cucumber feature. Is there a way to get the last HTTP response(s) which VCR have recorded?

The feature looks like this

    @vcr
    Scenario: Send hipchat message when task created
      Given an hipchat_sample integration exists with app: app "teamway"
      When I create an "ActionMailer::Error" task to "Teamway"
      And all jobs are worked off # invoke Delayed::Worker.new.work_off
      Then a hipchat message should be sent "ActionMailer::Error"

In my step definition I want to check the response body:

    Then /^a hipchat message should be sent "(.*?)"$/ do |arg1|
      # Like this:
      # VCR::Response.body.should == arg1
    end

VCR already records the request and response, but I do not know how to take them. I think of something similar to catching the emails sent with Pickle's steps. Does anybody have an idea how to do this?

I use rails 3.2.8, cucumber-rails 1.3 and vcr 2.2.4 (with webmock).

Best regards Torsten


Source: (StackOverflow)

Webmock and VCR, allow Http Connections if there is no cassette

I have a problem, I can run a test that uses vcr on its own and it works, it creates the cassette and it uses that on the next test. Great.

The problem is when I run all my tests together this particular test fails, because webmock disables http connections, I have seen this example on the Github repo page that explains how to expect real and not stubbed requests

My question is how Do I say: Allow Http connections for requests UNLESS there is a cassette. It should also CREATE the cassette when HTTP connections are allowed.

The VCR Settings

require 'vcr'

VCR.configure do | c |
  if !ARGV.first.nil?
    c.default_cassette_options = { :record => :new_episodes, :erb => true }
    c.filter_sensitive_data('<BLACKBIRD_API_KEY>') {YAML.load(File.read('config/application.yml'))['BLACKBIRD_API_KEY'].to_s}
    c.filter_sensitive_data('<BLACKBIRD_API_URL>') {YAML.load(File.read('config/application.yml'))['BLACKBIRD_API_URL'].to_s}
    c.debug_logger = File.open(ARGV.first, 'w')
    c.cassette_library_dir = 'spec/vcr'
    c.hook_into :webmock
  end
end

the above if statement exists because not EVERY test creates a cassette. So we want them to run when a cassette isn't needed.

The Test

require 'spec_helper'

describe Xaaron::Publishers::Users do

  context "publish created users" do
    before(:each) do
      Xaaron.configuration.reset
      no_user_member_roles_relation

      Xaaron.configuration.publish_to_black_bird = true
      Xaaron.configuration.black_bird_api_url = YAML.load(File.read('config/application.yml'))['BLACKBIRD_API_URL']
      Xaaron.configuration.black_bird_api_key =YAML.load(File.read('config/application.yml'))['BLACKBIRD_API_KEY']
    end

    it "should publish to blackbird" do
      VCR.use_cassette 'publisher/create_user_response' do
        expect(
          Xaaron::Publishers::Users.publish_new_user({user: {
            first_name: 'adsadsad', user_name: 'sasdasdasdsa'  ,
            email: 'asdassad@sample.com', auth_token: 'asdsadasdasdsa'
          }}).code
        ).to eql 200
      end
    end
  end

end

Runs fine on its own, creates the cassette, fails when run with all other tests due to webmock.

The Failure

Failure/Error: Xaaron::Publishers::Users.publish_new_user({user: {
 WebMock::NetConnectNotAllowedError:
   Real HTTP connections are disabled. Unregistered request: GET some_site_url_here with headers {'Http-Authorization'=>'api_key_here', 'User-Agent'=>'Typhoeus - https://github.com/typhoeus/typhoeus'}

   You can stub this request with the following snippet:

   stub_request(:get, "some site url here").
     with(:headers => {'Http-Authorization'=>'some api key here', 'User-Agent'=>'Typhoeus - https://github.com/typhoeus/typhoeus'}).
     to_return(:status => 200, :body => "", :headers => {})

Source: (StackOverflow)