Stubbing with Faraday and Rspec

michael picture michael · Jan 15, 2013 · Viewed 11.5k times · Source

I have a model that looks like this:

class Gist
    def self.create(options)
    post_response = Faraday.post do |request|
      request.url 'https://api.github.com/gists'
      request.headers['Authorization'] = "Basic " + Base64.encode64("#{GITHUB_USERNAME}:#{GITHUB_PASSWORD}")
      request.body = options.to_json
    end
  end
end

and a test that looks like this:

require 'spec_helper'

describe Gist do
  context '.create' do
    it 'POSTs a new Gist to the user\'s account' do
      Faraday.should_receive(:post)
      Gist.create({:public => 'true',
                   :description => 'a test gist',
                   'files' => {'test_file.rb' => 'puts "hello world!"'}})
    end
  end
end

This test doesn't really satisfy me, though, as all I'm testing is that I'm making some POST with Faraday, but I can't actually test the URL, headers, or body, since they're passed in with a block. I tried to use the Faraday test adaptor, but I don't see any way of testing the URL, headers, or body with that, either.

Is there a better way to write my Rspec stub? Or am I able to use the Faraday test adaptor in some way I haven't been able to make sense of?

Thanks!

Answer

michael picture michael · Jan 16, 2013

My friend @n1kh1l pointed me to the and_yield Rspec method and this SO post that let me write my test like this:

require 'spec_helper'

describe Gist do
  context '.create' do
    it 'POSTs a new Gist to the user\'s account' do
      gist = {:public => 'true',
              :description => 'a test gist',
              :files => {'test_file.rb' => {:content => 'puts "hello world!"'}}}

      request = double
      request.should_receive(:url).with('https://api.github.com/gists')
      headers = double
      headers.should_receive(:[]=).with('Authorization', "Basic " + Base64.encode64("#{GITHUB_USERNAME}:#{GITHUB_PASSWORD}"))
      request.should_receive(:headers).and_return(headers)
      request.should_receive(:body=).with(gist.to_json)
      Faraday.should_receive(:post).and_yield(request)

      Gist.create(gist)
    end
  end
end