How to test HTTParty API call with Ruby and RSpec

There are multiple ways you could approach this problem.

You could, as @anil suggested, use a library like webmock to mock the underlying HTTP call. You could also do something similar with VCR (https://github.com/vcr/vcr) which records the results of an actual call to the HTTP endpoint and plays back that response on subsequent requests.

But, given your question, I don't see why you couldn't just use an Rspec double. I'll show you how below. But, first, it would be a bit easier to test the code if it were not all in the constructor.

github_api.rb

require 'httparty'

class GithubApi
  attr_reader :username

  def initialize(username)
    @username = username
  end

  def favorite_language
    # method to calculate which language is used most by username
  end

  def languages
    # method to grab languages from repos
  end

  def repos
    repos ||= do
      response = HTTParty.get("https://api.github.com/users/#{username}/repos")
      JSON.parse(response.body)
    end
  end
end

Note that you do not need to reference the @username variable in the url because you have an attr_reader.

github_api_spec.rb

require './app/models/github_api'
require 'spec_helper'

describe GithubApi do
  subject(:api) { described_class.new(username) }

  let(:username) { 'username' }

  describe '#repos' do
    let(:github_url) { "https://api.github.com/users/#{username}/repos" }
    let(:github_response) { instance_double(HTTParty::Response, body: github_response_body) }
    let(:github_response_body) { 'response_body' }

    before do
      allow(HTTParty).to receive(:get).and_return(github_response)
      allow(JSON).to receive(:parse)

      api.repos
    end

    it 'fetches the repos from Github api' do
      expect(HTTParty).to have_received(:get).with(github_url)
    end

    it 'parses the Github response' do
      expect(JSON).to have_received(:parse).with(github_response_body)
    end
  end
end

Note that there is no need to actually load or parse any real JSON. What we're testing here is that we made the correct HTTP call and that we called JSON.parse on the response. Once you start testing the languages method you'd need to actually load and parse your test file, like this:

let(:parsed_response) { JSON.parse(File.read('path/to/test/file.json')) }

You can mock those API calls using https://github.com/bblimke/webmock and send back mock.json using webmock. This post, https://robots.thoughtbot.com/how-to-stub-external-services-in-tests walks you through the setup of webmock with RSpec (the tests in the post mock GitHub API call too)