我正在使用HTTParty gem来调用GitHub API,以访问用户的存储库列表。
这是一个使用Sinatra的非常简单的应用程序,它基于用户存储库中出现的最常见的语言来显示用户喜欢的编程语言。
我对如何编写RSpec期望值感到有些困惑,该期望值可以模拟实际的API调用,而只是检查是否返回了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
答案 0 :(得分:2)
您可以使用https://github.com/bblimke/webmock模拟这些API调用,并使用webmock发送回ock.mock.json。这篇文章https://robots.thoughtbot.com/how-to-stub-external-services-in-tests引导您使用RSpec设置webmock(文章模拟GitHub API调用中的测试也是如此)
答案 1 :(得分:2)
有多种方法可以解决此问题。
您可以按照@anil的建议,使用像webmock这样的库来模拟基础的HTTP调用。您还可以使用VCR(https://github.com/vcr/vcr)进行类似操作,该记录会记录对HTTP端点的实际调用结果,并在后续请求中回放该响应。
但是,鉴于您的问题,我不明白为什么您不能只使用Rspec double。我将在下面告诉您。但是,首先,如果代码不在构造函数中,则测试起来会容易一些。
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(repos.body)
end
end
end
请注意,由于您有@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)) }