WebMock simulate failing API (no internet, timeout ++)
Asked Answered
C

2

27

I am trying to simulate unexpected behaviour from a web api, such as not finding the server and timeouts, using webmock.

What would be the best way to do this? All I can think of is to do something like this:

stubbed_request = stub_request(:get, "#{host}/api/something.json").
with(:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json', 'User-Agent'=>'Ruby'}).
to_return(:status => [500, "Internal Server Error"])

That should work for things like 404 etc., but how can I test timeouts, server not found/offline server, and no internet connection?

Cymbal answered 28/8, 2014 at 15:9 Comment(0)
C
39

After some digging I found some solutions to this.

Apparently you can change the to_return(...) to to_timeout, which will throw a timeout error. You can also have to_raise(StandardError). For full reference, see https://github.com/bblimke/webmock#raising-timeout-errors.

Timeout, or server not found, example:

stubbed_request = stub_request(:get, "#{host}/api/something.json").
with(:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json', 'User-Agent'=>'Ruby'}).
to_timeout

Raise StandardError, or no internet/other exception, example:

stubbed_request = stub_request(:get, "#{host}/api/something.json").
with(:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json', 'User-Agent'=>'Ruby'}).
to_raise(StandardError)

#Error example 2:
stubbed_request = stub_request(:get, "#{host}/api/something.json").
with(:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json', 'User-Agent'=>'Ruby'}).
to_raise("My special error")

There you go, not too hard after all.


I have no idea how I didn't find this the first time. Anyway, hope this helps someone out one day.

Cymbal answered 28/8, 2014 at 22:58 Comment(3)
This did help, shame on me for not finding to_raise and to_timeout sooner. Thanks!Ibrahim
Strange, if I use to_timeout I cant avoid a RestClient::RequestTimeout being thrown and my test errors out. If I use to_raise in any fashion, I get a SystemStackError: stack level too deep.Rotate
To be honest it sounds like you have a bug in your code :/Cymbal
H
1

Came across this question and decided to add supportive materials. According to a discussion in WebMock issue (https://github.com/bblimke/webmock/issues/16), the timeout can be simulated in two ways.

The first way is two use .to_raise(e):

stubbed_request = stub_request(:get, "#{host}/api/something.json").
with(:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json', 'User- 
Agent'=>'Ruby'}).to_raise(e)

Where e is a library specific timeout exception. quotation: "The whole point of WebMock is to be HTTP client library independent so to_timeout should work with every library. The problem is that different libraries return different errors, ie Net::HTTP return Ruby Timeout::Error while HTTPClient raises HTTPClient:: TimeoutError. This behavior can be replicated in WebMock but the error handling code will have to be different any time you change the library."

The second way is to use the following sample:

stub_request(:any, 'www.example.net').to_timeout
RestClient.post('www.example.net', 'abc')    # ===> RestClient::RequestTimeout  

Here is the original source: https://github.com/bblimke/webmock/issues/16

Heighttopaper answered 10/11, 2018 at 20:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.