Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails: Best way to test a failed call to a third party API

I call a third party web service right now as part of my application. I am using the RestClient gem in order to do this. There are a ton of tools available to do the same thing, so that should not matter.

What I'm curious about is having good enough tests, nothing too fancy, where I can simulate how my application responds when the third party web service is unavailable for whatever reason. Be it that I exceeded a rate limit or a timeout due to network latency/complications, I just want to be able to take something like an HTTP status code and test what my application does in that event.

What's the best way to do this with Test::Unit? Right now the call to the third party service is encapsulated inside of one of my controllers. I have a simple module with some wrapper methods for the different end points of the remote service. I just want to make sure that my application does the right things when the service is or isn't available.

Is using an additional framework next to Test::Unit that can 'stub' the right way to go about doing this? Obviously I can't force a network timeout and starting to hack with things like IPtables just for tests is not worth the time. I'm sure this problem has been solved a million times as integrating things such as Facebook and Twitter into web applications is so popular these days. How do you test for failure when reaching those APIs in a robust/controlled format?

like image 911
randombits Avatar asked Oct 24 '11 22:10

randombits


People also ask

How do I stub an external service test?

Create a Fake (Hello Sinatra!) First we use Webmock to route all requests to our Sinatra application, FakeGitHub . Next we'll create the FakeGitHub application. Download a sample JSON response and store it in a local file. Update the test, and verify the expected stub response is being returned.

How do I run a test case in Ruby?

We can run all of our tests at once by using the bin/rails test command. Or we can run a single test file by passing the bin/rails test command the filename containing the test cases. This will run all test methods from the test case.

What are test cases in Ruby?

Tests for a particular unit of code are grouped together into a test case, which is a subclass of Test::Unit::TestCase. Assertions are gathered in tests, member functions for the test case whose names start with test_.


2 Answers

I would recommend using something like webmock to mock all of your http requests (not just to mock a failed request); it'll greatly speed up your test suite instead of having to actually hit the third party service every time you run the tests.

Webmock supports Rest Client and Test::Unit. Just put this code in your test/test_helper.rb file:

require 'webmock/test_unit' 

As an example, to test a network timeout:

stub_request(:any, 'www.example.net').to_timeout
RestClient.post('www.example.net', 'abc')    # ===> RestClient::RequestTimeout
like image 106
Dylan Markow Avatar answered Nov 08 '22 12:11

Dylan Markow


railscast: 291 (subscriber only) talks about testing with VCR and rspec (i know, not it's not Test:Unit)

anyway you could look into using VCR for this sort of thing

like image 1
stephenmurdoch Avatar answered Nov 08 '22 12:11

stephenmurdoch