how do I test (rspec) a http request that takes too long?

11,842

Solution 1

If you purely care about Net::HTTP raising a Timeout::Error, you could always just force it to return the error with a mock, here is a good compilation of various things you can use with RSpec.

It would depend on your exact Net::HTTP request, but something such as Net::HTTP.should_receive(:request_get).and_raise(Timeout::Error) would skip any networking calls and just raise the error immediately.

Solution 2

The below test fails if request doesn't finish in 20 seconds. It also fails if the code in the lambda doesn't raise Timeout::Error.

So, successful scenario is when long_running_stuff raises exception in less than 20 seconds.

require 'timeout'

describe "Test" do 
  it "should timeout if the request takes too long" do 
    Timeout::timeout(20) do # 20 seconds
      lambda {
         long_running_stuff(:timeout => 10.seconds)
      }.should raise_error(Timeout::Error)
    end
  end 
end

Solution 3

I realize this question is ancient, but here's another solution using the WebMock gem:

stub_request(:any, 'www.google.com').to_timeout

Another nice benefit to stubbing the request with Webmock is that this will continue to work even if you swap out your HTTP client, which decouples your tests from your code.

Share:
11,842
dvliman
Author by

dvliman

Updated on June 12, 2022

Comments

  • dvliman
    dvliman almost 2 years

    How do I test the behavior if a request takes too long with rspec?

    I am thinking of using thread to mock this:

    describe "Test" do 
      it "should timeout if the request takes too long" do 
        lambda {
          thread1 = Thread.new { #net::http request to google.com }
          thread2 = Thread.new { sleep(xx seconds) }
          thread1.join 
          thread2.join
        }.should raise_error
      end 
    end
    

    I want to make sure that after the request is first made, another thread "kicks in" which in this case is just a sleep for xx seconds. Then I should expect the request to timeout because it takes too long to execute

    I think that there are better ways to do this. Given the fact that the url I am requesting is not relevant. I just want to test that it will indeed timeout if it takes too long to execute.

    Can I use stub(), expect() or any rspec features to simulate this?

    Is there any way that I can pass in a 'block' into stub method

    http_request_to_google.stub(:connection).executethisblock(sleep for xx seconds)
    .and_throw error ?
    

    any help is appreciated