I'm working on a project that gets data from an external REST API (from a social network such as Facebook, Twitter or Instagram).
I'm not sure that what I'm doing is right or wrong so I need some guidance. I don't know how, when people create an app which depends on data from outside (a REST API or crawling data), they do TDD with it.
My question is: I'm trying to do a TDD test on a method that calls an external REST API. Is this right or wrong?
For example:
I have code like this:
API_VERSION = "v2.5"
FIELD_PAGE_GRAPH = %w(id name picture{url} likes cover is_community_page category link website has_added_app
talking_about_count username founded phone mission location is_published description can_post checkins company_overview
general_info parking hours payment_options access_token
)
FIELD_STREAM_GRAPH = %w(id message story comments.summary(true) likes.summary(true).limit(500) from to link shares created_time
updated_time type is_published attachments scheduled_publish_time application
)
def self.get_stat_facebook(page_id,access_token=nil)
graph = Koala::Facebook::API.new(access_token)
graph.get_objects(page_id.to_s,{:fields => FIELD_PAGE_GRAPH}, {:api_version => API_VERSION})
end
def self.get_feed_facebook(page_id,access_token=nil, options = {})
options = options.with_indifferent_access
retry_time = 0
begin
graph = Koala::Facebook::API.new(access_token)
params = {:fields => FIELD_STREAM_GRAPH, :limit => 25}
params.merge!({:since => options[:_since].to_i}) if options[:_since].present?
params.merge!({:until => options[:_until].to_i}) if options[:_until].present?
results = []
loop do
graph_response = graph.get_object(page_id.to_s+"/feed", params, {:api_version => API_VERSION})
break if graph_response.blank?
results = results+graph_response
break if options[:_since].blank?
params[:until] = graph_response.sort_by!{|result| result['created_time']}.first['created_time'].to_time.to_i-1
end
rescue Koala::Facebook::ServerError
sleep 1
retry_time += 1
retry if retry_time <= 3
end
filter_owner_page(results, page_id)
end
Then I have a spec like
require 'spec_helper'
RSpec.describe SocialNetwork do
context ".get_stat_facebook" do
it "when access token is expired"
it "when access token is not expired"
it "when page id is not exist"
it "when page id is exist"
end
context ".get_feed_facebook" do
it "when access token is expired"
it "when access token is not expired"
it "when page id is not exist"
it "when page id is exist"
it "data contain id field"
it "data contain message field"
it "data contain attachment field"
end
end
Yes, it's appropriate for tests to hit external services, but you can minimize the impact of that on your test suite in a couple of ways.
I would test this code as follows:
Write RSpec specs (unit tests) for SocialNetwork
.
SocialNetwork
, ones that just test variations of calls that you already tested, stub out Koala.It's hard to explain exactly which tests should hit Facebook and which should use stubs without having them in front of us. See how it goes and post again if you need more advice.