Faking and testing the network with WebMock

Updated . Posted . Visible to the public. Repeats.

An alternative to this technique is using VCR. VCR allows you to record and replay real HTTP responses, saving you the effort to stub out request/response cycles in close details. If your tests do require close inspection of requests and responses, Webmock is still the way.


WebMock Show archive.org snapshot is an alternative to FakeWeb Show archive.org snapshot when testing code that uses the network. You should probably learn it together with RestClient Show archive.org snapshot , which is an awesome alternative to net/http and shares many concepts with WebMock.

You can fake a remote server response like this:

stub_request(:get, 'http://host/api').to_return(:body => 'fake body')

You can test that a request has happened like this:

stub_request(:get, 'http://host/api').to_return(:body => 'fake body')
RestClient.get('http://host/api')
WebMock.should have_requested(:get ,'http://host/api')

Params are tricky

Testing for request params is a little tricky because Rails hides details about how HTTP works. In particular GET requests encode their params in the URL while POST, PUT and DELETE requests encode their params in the body. Neither WebMock nor RestClient will hide that from you (for reasons outside the scope of this article).

Compare stubbing a POST request with params...

stub_request(:post, 'http://host/api').with(:body => { :name => 'value' }).to_return(:body => 'fake body')

... to stubbing a GET request with params:

 stub_request(:get, 'http://host/api?name=value').to_return(:body => 'fake body')
stub_request(:get, 'http://host/api').with(:query => { :name => 'value' }).to_return(:body => 'fake body') # alternate way to write the above

Also compare expecting a GET request with params...

stub_request(:get, 'http://host/api').with(:query => { :key => 'value' }).to_return(:body => 'fake body')
RestClient.get('http://host/api?key=value') 
RestClient.get('http://host/api', :params => { :key => 'value' }) # alternate way to write the above
WebMock.should have_requested(:get ,'http://host/api?key=value')
WebMock.should have_requested(:get ,'http://host/api').with(:query => { :key => 'value' }) # alternate way to write the above

... to expecting a POST request with params:

stub_request(:post, 'http://host/api').with(:body => { :key => 'value' }).to_return(:body => 'fake body')
RestClient.post('http://host/api', :key => 'value') 
WebMock.should have_requested(:post ,'http://host/api')

Here is a way to test that certain query parameters are included in a request. This might come in handy if there are a lot of params or you are only interested in certain query params:

WebMock.should have_requested(:get, /http:\/\/host/api/)
  .with(query: hash_including({ closed: 'true' }))

For this to work properly, make sure you've got WebMock >1.18.

Henning Koch
Last edit
Michael Leimstädtner
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra dev (2010-08-28 20:08)