Today it is quite common to write applications that depend on third-party APIs, or even internal APIs, in this modularized digital world. But it makes testing tricky because dependency has an impact during the testing process:

  • Test cases will be slow
  • Test cases might fail if the third-party service is down
  • Test cases will consume resources in the external service (allowed rate limits)
  • Sensitive information must be available to make them work (API Keys, secrets, etc)

That’s enough reasons to think of better ways to improve the process, and this is where HTTPretty comes to the rescue.

HTTPretty

HTTPretty is just a mocking library for HTTP requests. Quoting their original words:

Once upon a time a python developer wanted to use a RESTful api, everything was fine but until the day he needed to test the code that hits the RESTful API: what if the API server is down? What if its content has changed?

Lucky for us HTTPretty has a really simple interface and since it monkey patches Python’s socket module, it works independently of the HTTP library used.

Example usage

Lets start with a simple example, let’s mock a 200 response (we will be using the requests library for its simplicity):

import requests
import httpretty

# First enable HTTPretty (will monkey patch the socket module)
httpretty.enable()
# Register an URI to patch
httpretty.register_uri(httpretty.GET, 'http://example.com/', status=200)
response = request.get('http://example.com/')

print(response.status_code)
# Outputs: 200
print(response.content)
# Outputs: HTTPretty :)

# Remove the patches
httpretty.disable()

We can override the response content of course:

import requests
import httpretty

httpretty.enable()
httpretty.register_uri(httpretty.GET, 'http://example.com/',
                       body='Overriding the response body',
                       status=200)
response = request.get('http://example.com/')

print(response.status_code)
# Outputs: 200
print(response.content)
# Outputs: Overriding the response body

httpretty.disable()

We can make the response content to be of any type, JSON for example:

import json
import requests
import httpretty

httpretty.enable()
json_body = json.dumps({'status': 'ok', 'value': '123'})
httpretty.register_uri(httpretty.GET, 'http://example.com/',
                       body=json_body,
                       content_type='application/json',
                       status=200)
response = request.get('http://example.com/')
print(response.status_code)

# Outputs: 200
print(response.content)
# Outputs: '{"status": "ok", "value": "123"}'
print(response.json())
# Outputs: {u'status': u'ok', u'value': u'123'}

httpretty.disable()

For simplicity, there’s a decorator that will call enable() and disable() for us:

import requests
import httpretty

@httpretty.activate
def test():
    httpretty.register_uri(httpretty.GET, 'http://example.com',
                           status=200, body='Testing decorator')
    return requests.get('http://example.com')

response = test()

print(response.status_code)
# Outputs: 200
print(response.content)
# Outputs: Testing decorator
print(httpretty.is_enabled())
# Outputs: False

HTTPretty also support the many HTTP methods beside GET, they can be accessed at:

  • httpretty.DELETE
  • httpretty.PUT
  • httpretty.GET
  • httpretty.OPTIONS
  • httpretty.HEAD
  • httpretty.PATCH
  • httpretty.POST

Other features are:

  • Add custom headers with the adding_headers parameter.
  • Define multiple response values with the responses parameter, the responses will be returned in order they are defined.
  • Set a function as body parameter.
  • The URI can be defined as a regular expression.

Conclusion

HTTPretty is great tool that helps to speed up the test cases that depend on external APIs. It also help to ensure that the application logic is well defined with the expected responses from the services, and if the third-party changes, it’s not a fault in your code.