Если вы используете в своём проекте requests, то наверняка сталкиваетесь с проблемами тестирования. На помощь придёт библиотека responses, которая позволяет делать моки ответов вызовов requests.

Мы в своём проекте используем эту библиотеку не так давно. Хотя из‑за особенностей окружения проекта мы часто обращаемся к огромному количеству REST API смежных сервисов. И до того, как requests попалась нам на глаза, код тестов представлял из себя нечто невообразимое, трудночитаемое.

Пользоваться библиотекой невероятно просто. Для иллюстрации — пара примеров из документации.

Пример 1

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"}'

Пример 2

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')
    assert resp.status_code == 404

Настоятельно рекомендую попробовать использовать responses в тестах. Местами мы наблюдаем неожиданный эффект: если пользоваться в тестах этой библиотекой, то часть кода, которая использует requests, можно переписать более внятно и компактно — без оглядки на то, что какую‑то часть нужно будет мокать для тестов.