user3379926
user3379926

Reputation: 3945

Testing this rails controller - While making API Calls?

I am no stranger to testing. I pride my self on have 97% - 100% test coverage. In fact anything below 95% is poor (but thats off topic). I have the following rails controller:

module Api
  module Internal
    class TwitterController < Api::V1::BaseController

      # Returns you 5 tweets with tons of information.
      #
      # We want 5 specific tweets with the hash of #AisisWriter.
      def fetch_aisis_writer_tweets
        tweet_array = [];
        tweet = twitter_client.search("#AisisWriter").take(5).each do |tweet|
          tweet_array.push(tweet)
        end

        render json: tweet_array
      end

      private

      # Create a twitter client connection.
      def twitter_client
        client = Twitter::REST::Client.new do |config|
          config.consumer_key               = ENV['CONSUMER_KEY']
          config.consumer_secret            = ENV['CONSUMER_SECRET_KEY']
          config.access_token               = ENV['ACCESS_TOKEN']
          config.access_token_secret        = ENV['ACCESS_TOKEN_SECRET']
        end
      end

    end
  end
end

It's extremely basic to see whats going on. Now I could write the rspec tests to say call this action, I expect json['bla']['text'] to eql bla.

But there is a couple issues. In order to effectively test this you need twitter API credentials. Thats coupling my code with another service that I am hoping is up and running.

In fact my controller is essentially coupled to twitter.

So - My question is, with out having to mock a web service or a api call (I have seen some blog posts out there on this, and for this piece of code, I feel they are over kill) - How would you test this?

Some people have suggested VCR. Any thoughts on testing API calls like this?

Upvotes: 1

Views: 342

Answers (1)

Ryan Mitchell
Ryan Mitchell

Reputation: 1410

I've found VCR to be a great tool for tests like this - where you don't need a ton of control over what the external service returns, because you don't have a lot of cases to test. You just want to eliminate test flakiness based on whether or not the service is up, and you want to make sure that you get exactly the same fake response every time. I wouldn't say VCR is overkill at all, it's very simple to use - you just wrap your test in a use_cassette block, run your test, and VCR records the actual response from the service and uses it as the mocked response from then on.

I will say that the "cassettes" that VCR uses to store the mocked responses are fairly complex YAML, and they're not super readable/easy to edit. If you want to be able to easily manipulate the data that's returned so that you can test several code paths, and easily read it so that your mocked data can serve as documentation of the code, I'd look into something more like HttpMock.

One other option, of course, would be to just stub out the private method that calls the external service and have it return your mock data directly. Usually I'd avoid that, so that you can refactor your private method and still be covered, but it might be an option in some cases where the private method is dead simple and unlikely to change, and stubbing it out makes for significantly cleaner tests.

Upvotes: 1

Related Questions