Read more

Faking and testing the network with WebMock

Henning Koch
August 28, 2010Software engineer at makandra GmbH

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.


Illustration web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
Read more Show archive.org snapshot

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.

Posted by Henning Koch to makandra dev (2010-08-28 22:08)