Posted over 8 years ago. Visible to the public. Repeats. Linked content.

Faking and testing the network with WebMock

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 is an alternative to FakeWeb when testing code that uses the network. You should probably learn it together with RestClient, which is an awesome alternative to net/http and shares many concepts with WebMock.

You can fake a remote server response like this:

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

You can test that a request has happened like this:

Copy
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…

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

… to stubbing a GET request with params:

Copy
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…

Copy
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:

Copy
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:

Copy
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.

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Owner of this card:

Avatar
Henning Koch
Last edit:
about 2 years ago
by Daniel Straßner
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Henning Koch to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more