【问题标题】:How to test HTTParty API call with Ruby and RSpec如何使用 Ruby 和 RSpec 测试 HTTParty API 调用
【发布时间】:2018-12-06 15:10:31
【问题描述】:

我正在使用 HTTParty gem 调用 GitHub API 以访问用户的存储库列表。

这是一个使用 Sinatra 的非常简单的应用程序,它根据用户存储库中出现的最常用语言显示用户最喜欢的编程语言。

我对如何编写一个模拟实际 API 调用的 RSpec 期望感到有点困惑,而只是检查是否返回了 json 数据。

我有一个模拟 .json 文件,但不知道如何在我的测试中使用它。

有什么想法吗?

github_api.rb

require 'httparty'

class GithubApi
  attr_reader :username, :data, :languages

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

github_api_spec.rb

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

describe GithubApi do
  let(:github_api) { GithubApi.new('mock_user') }

  it "receives a json response" do

  end
end

为清楚起见,其余文件:

results.rb

require 'httparty'
require_relative 'github_api'

class Results

 def initialize(github_api = Github.new(username))
   @github_api = github_api
   @languages = []
 end

 def get_languages
   @github_api.data.each do |repo|
     @languages << repo["language"]
   end
 end

 def favourite_language
   get_languages
   @languages.group_by(&:itself).values.max_by(&:size).first
 end
end

application_controller.rb

require './config/environment'
require 'sinatra/base'
require './app/models/github_api'

class ApplicationController < Sinatra::Base

  configure do
    enable :sessions
    set :session_secret, "@3x!ilt£"
    set :views, 'app/views'
  end

  get "/" do
    erb :index
  end

  post "/user" do
    @github = GithubApi.new(params[:username])
    @results = Results.new(@github)
    @language = @results.favourite_language
    session[:language] = @language
    session[:username] = params[:username]
    redirect '/results'
  end

  get "/results" do
    @language = session[:language]
    @username = session[:username]
    erb :results
  end

run! if app_file == $0

end

【问题讨论】:

    标签: ruby rspec httparty


    【解决方案1】:

    有多种方法可以解决这个问题。

    正如@anil 建议的那样,您可以使用 webmock 之类的库来模拟底层 HTTP 调用。您还可以使用 VCR (https://github.com/vcr/vcr) 执行类似的操作,它会记录对 HTTP 端点的实际调用结果并在后续请求中播放该响应。

    但是,鉴于您的问题,我不明白您为什么不能只使用 Rspec 替身。我会在下面告诉你怎么做。但是,首先,如果代码不是全部在构造函数中,测试代码会更容易一些。

    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
    

    请注意,您不需要在 url 中引用 @username 变量,因为您有一个 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
    

    请注意,不需要实际加载或解析任何真实的 JSON。我们在这里测试的是我们进行了正确的 HTTP 调用,并且我们在响应中调用了JSON.parse。一旦你开始测试languages 方法,你就需要实际加载和解析你的测试文件,像这样:

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

    【讨论】:

    • 非常感谢您提供的有用解决方案!正是我在理解如何测试和测试什么方面所追求的,非常感谢:)
    • 非常有帮助,谢谢!
    【解决方案2】:

    您可以使用 https://github.com/bblimke/webmock 模拟这些 API 调用,并使用 webmock 发回 mock.json。这篇 https://robots.thoughtbot.com/how-to-stub-external-services-in-tests 的博文将带您完成使用 RSpec 设置 webmock(post mock GitHub API 调用中的测试)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-30
      • 1970-01-01
      • 2018-02-21
      • 1970-01-01
      相关资源
      最近更新 更多