Skip to main content

A utility library for mocking out the `requests` Python library.

Project description

https://travis-ci.org/getsentry/responses.png?branch=master

A utility library for mocking out the requests Python library.

Response body as string

import responses
import requests

@responses.activate
def test_my_api():
    responses.add(responses.GET, 'http://twitter.com/api/1/foobar',
                  body='{"error": "not found"}', status=404,
                  content_type='application/json')

    resp = requests.get('http://twitter.com/api/1/foobar')

    assert resp.json() == {"error": "not found"}

    assert len(responses.calls) == 1
    assert responses.calls[0].request.url == 'http://twitter.com/api/1/foobar'
    assert responses.calls[0].response.text == '{"error": "not found"}'

You can also specify a JSON object instead of a body string.

import responses
import requests

@responses.activate
def test_my_api():
    responses.add(responses.GET, 'http://twitter.com/api/1/foobar',
                  json={"error": "not found"}, status=404)

    resp = requests.get('http://twitter.com/api/1/foobar')

    assert resp.json() == {"error": "not found"}

    assert len(responses.calls) == 1
    assert responses.calls[0].request.url == 'http://twitter.com/api/1/foobar'
    assert responses.calls[0].response.text == '{"error": "not found"}'

Request callback

import json

import responses
import requests

@responses.activate
def test_calc_api():

    def request_callback(request):
        payload = json.loads(request.body)
        resp_body = {'value': sum(payload['numbers'])}
        headers = {'request-id': '728d329e-0e86-11e4-a748-0c84dc037c13'}
        return (200, headers, json.dumps(resp_body))

    responses.add_callback(
        responses.POST, 'http://calc.com/sum',
        callback=request_callback,
        content_type='application/json',
    )

    resp = requests.post(
        'http://calc.com/sum',
        json.dumps({'numbers': [1, 2, 3]}),
        headers={'content-type': 'application/json'},
    )

    assert resp.json() == {'value': 6}

    assert len(responses.calls) == 1
    assert responses.calls[0].request.url == 'http://calc.com/sum'
    assert responses.calls[0].response.text == '{"value": 6}'
    assert (
        responses.calls[0].response.headers['request-id'] ==
        '728d329e-0e86-11e4-a748-0c84dc037c13'
    )

Instead of passing a string URL into responses.add or responses.add_callback you can also supply a compiled regular expression.

import re
import responses
import requests

# Instead of
responses.add(responses.GET, 'http://twitter.com/api/1/foobar',
              body='{"error": "not found"}', status=404,
              content_type='application/json')

# You can do the following
url_re = re.compile(r'https?://twitter.com/api/\d+/foobar')
responses.add(responses.GET, url_re,
              body='{"error": "not found"}', status=404,
              content_type='application/json')

A response can also throw an exception as follows.

import responses
import requests
from requests.exceptions import HTTPError

exception = HTTPError('Something went wrong')
responses.add(responses.GET, 'http://twitter.com/api/1/foobar',
              body=exception)
# All calls to 'http://twitter.com/api/1/foobar' will throw exception.

Responses as a context manager

import responses
import requests


def test_my_api():
    with responses.RequestsMock() as rsps:
        rsps.add(responses.GET, 'http://twitter.com/api/1/foobar',
                 body='{}', status=200,
                 content_type='application/json')
        resp = requests.get('http://twitter.com/api/1/foobar')

        assert resp.status_code == 200

    # outside the context manager requests will hit the remote server
    resp = requests.get('http://twitter.com/api/1/foobar')
    resp.status_code == 404

Assertions on declared responses

By default Responses will raise an assertion error if a url was registered but not accessed. This can be disabled by passing the assert_all_requests_are_fired value:

import responses
import requests


def test_my_api():
    with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps:
        rsps.add(responses.GET, 'http://twitter.com/api/1/foobar',
                 body='{}', status=200,
                 content_type='application/json')

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

responses-0.5.1.tar.gz (10.2 kB view hashes)

Uploaded Source

Built Distribution

responses-0.5.1-py2.py3-none-any.whl (7.5 kB view hashes)

Uploaded Python 2 Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page