Skip to main content

aioresponses-ng

PyPI version CI

This is a maintained fork of aioresponses with aiohttp compatibility fixes. The API is identical - just swap the package name.

Aioresponses is a helper to mock/fake web requests in python aiohttp package.

For the requests module there are a lot of packages that help us with testing (e.g. httpretty, responses, requests-mock).

When it comes to testing asynchronous HTTP requests it is a bit harder (at least at the beginning). The purpose of this package is to provide an easy way to test asynchronous HTTP requests.

Installing

pip install aioresponses-ng

Supported versions

  • Python 3.10+
  • aiohttp>=3.9,<4.0

Usage

To mock out HTTP requests use aioresponses as a method decorator or as a context manager.

Response status code, body, payload (for json response) and headers can be mocked.

Supported HTTP methods: GET, POST, PUT, PATCH, DELETE and OPTIONS.

import aiohttp
import asyncio
from aioresponses import aioresponses

@aioresponses()
def test_request(mocked):
    loop = asyncio.get_event_loop()
    mocked.get('http://example.com', status=200, body='test')
    session = aiohttp.ClientSession()
    resp = loop.run_until_complete(session.get('http://example.com'))

    assert resp.status == 200
    mocked.assert_called_once_with('http://example.com')

For convenience use the payload argument to mock out JSON responses.

As a context manager

import asyncio
import aiohttp
from aioresponses import aioresponses

def test_ctx():
    loop = asyncio.get_event_loop()
    session = aiohttp.ClientSession()
    with aioresponses() as m:
        m.get('http://test.example.com', payload=dict(foo='bar'))

        resp = loop.run_until_complete(session.get('http://test.example.com'))
        data = loop.run_until_complete(resp.json())

        assert dict(foo='bar') == data
        m.assert_called_once_with('http://test.example.com')

Mocking HTTP headers

import asyncio
import aiohttp
from aioresponses import aioresponses

@aioresponses()
def test_http_headers(m):
    loop = asyncio.get_event_loop()
    session = aiohttp.ClientSession()
    m.post(
        'http://example.com',
        payload=dict(),
        headers=dict(connection='keep-alive'),
    )

    resp = loop.run_until_complete(session.post('http://example.com'))

    # note that we pass 'connection' but get 'Connection' (capitalized)
    # under the hood `multidict` is used to work with HTTP headers
    assert resp.headers['Connection'] == 'keep-alive'
    m.assert_called_once_with('http://example.com', method='POST')

Multiple responses for the same URL

import asyncio
import aiohttp
from aioresponses import aioresponses

@aioresponses()
def test_multiple_responses(m):
    loop = asyncio.get_event_loop()
    session = aiohttp.ClientSession()
    m.get('http://example.com', status=500)
    m.get('http://example.com', status=200)

    resp1 = loop.run_until_complete(session.get('http://example.com'))
    resp2 = loop.run_until_complete(session.get('http://example.com'))

    assert resp1.status == 500
    assert resp2.status == 200

Repeating responses

Useful for testing retry mechanisms.

  • By default, repeat=False means the response is used once (repeat=1 does the same).
  • Use repeat=n to repeat a response n times.
  • Use repeat=True to repeat a response indefinitely.
import asyncio
import aiohttp
from aioresponses import aioresponses

@aioresponses()
def test_multiple_responses(m):
    loop = asyncio.get_event_loop()
    session = aiohttp.ClientSession()
    m.get('http://example.com', status=500, repeat=2)
    m.get('http://example.com', status=200)  # takes effect after two preceding calls

    resp1 = loop.run_until_complete(session.get('http://example.com'))
    resp2 = loop.run_until_complete(session.get('http://example.com'))
    resp3 = loop.run_until_complete(session.get('http://example.com'))

    assert resp1.status == 500
    assert resp2.status == 500
    assert resp3.status == 200

Matching URLs with regular expressions

import asyncio
import aiohttp
import re
from aioresponses import aioresponses

@aioresponses()
def test_regexp_example(m):
    loop = asyncio.get_event_loop()
    session = aiohttp.ClientSession()
    pattern = re.compile(r'^http://example\.com/api\?foo=.*$')
    m.get(pattern, status=200)

    resp = loop.run_until_complete(session.get('http://example.com/api?foo=bar'))

    assert resp.status == 200

Redirect responses

import asyncio
import aiohttp
from aioresponses import aioresponses

@aioresponses()
def test_redirect_example(m):
    loop = asyncio.get_event_loop()
    session = aiohttp.ClientSession()

    # absolute URLs are supported
    m.get(
        'http://example.com/',
        headers={'Location': 'http://another.com/'},
        status=307
    )

    resp = loop.run_until_complete(
        session.get('http://example.com/', allow_redirects=True)
    )
    assert resp.url == 'http://another.com/'

    # relative URLs are also supported
    m.get(
        'http://example.com/',
        headers={'Location': '/test'},
        status=307
    )
    resp = loop.run_until_complete(
        session.get('http://example.com/', allow_redirects=True)
    )
    assert resp.url == 'http://example.com/test'

Passthrough to real servers

import asyncio
import aiohttp
from aioresponses import aioresponses

@aioresponses(passthrough=['http://backend'])
def test_passthrough(m, test_client):
    session = aiohttp.ClientSession()
    # this will actually perform a request
    resp = loop.run_until_complete(session.get('http://backend/api'))

Passthrough all unmatched requests

import asyncio
import aiohttp
from aioresponses import aioresponses

@aioresponses(passthrough_unmatched=True)
def test_passthrough_unmatched(m, test_client):
    url = 'https://httpbin.org/get'
    m.get(url, status=200)
    session = aiohttp.ClientSession()
    # this will actually perform a request
    resp = loop.run_until_complete(session.get('http://backend/api'))
    # this will not perform a request and resp2.status will return 200
    resp2 = loop.run_until_complete(session.get(url))

Throwing exceptions

import asyncio
from aiohttp import ClientSession
from aiohttp.http_exceptions import HttpProcessingError
from aioresponses import aioresponses

@aioresponses()
def test_how_to_throw_an_exception(m, test_client):
    loop = asyncio.get_event_loop()
    session = ClientSession()
    m.get('http://example.com/api', exception=HttpProcessingError('test'))

    # calling
    # loop.run_until_complete(session.get('http://example.com/api'))
    # will throw an exception.

Callbacks for dynamic responses

import asyncio
import aiohttp
from aioresponses import CallbackResult, aioresponses

def callback(url, **kwargs):
    return CallbackResult(status=418)

@aioresponses()
def test_callback(m, test_client):
    loop = asyncio.get_event_loop()
    session = ClientSession()
    m.get('http://example.com', callback=callback)

    resp = loop.run_until_complete(session.get('http://example.com'))

    assert resp.status == 418

Using with pytest fixtures

import pytest
from aioresponses import aioresponses

@pytest.fixture
def mock_aioresponse():
    with aioresponses() as m:
        yield m

Features

  • Easy to mock out HTTP requests made by aiohttp.ClientSession

License

MIT — see LICENSE for details.

Credits

Fork maintained by MountainGod2. Originally created by Pawel Nuckowski using Cookiecutter and the audreyr/cookiecutter-pypackage template.

Download files

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

Source Distribution

aioresponses_ng-0.8.2.tar.gz (19.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aioresponses_ng-0.8.2-py3-none-any.whl (10.8 kB view details)

Uploaded Python 3

File details

Details for the file aioresponses_ng-0.8.2.tar.gz.

File metadata

  • Download URL: aioresponses_ng-0.8.2.tar.gz
  • Upload date:
  • Size: 19.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for aioresponses_ng-0.8.2.tar.gz
Algorithm Hash digest
SHA256 0ee168f7bccfcc7990a995fcabf42bb84dd42faafaa30497c7108b093214633f
MD5 243ab59b31640efd18740544d737565f
BLAKE2b-256 646f6e317e805995b704894d9fc90ca63a87a567daf567e58db138659bf0abdc

See more details on using hashes here.

Provenance

The following attestation bundles were made for aioresponses_ng-0.8.2.tar.gz:

Publisher: release.yml on MountainGod2/aioresponses-ng

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file aioresponses_ng-0.8.2-py3-none-any.whl.

File metadata

File hashes

Hashes for aioresponses_ng-0.8.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9de28a0de0ad289c6317b56da2f81c846643e4b9c2fde32023c1509064fbb72d
MD5 db28a509281cecaf58ac3bcaa97533f2
BLAKE2b-256 a79d4ad5aebee5771ce0822135b6daaa21b45f44043b15eb1b7afc2faaeabf1c

See more details on using hashes here.

Provenance

The following attestation bundles were made for aioresponses_ng-0.8.2-py3-none-any.whl:

Publisher: release.yml on MountainGod2/aioresponses-ng

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.8.2 This release

2 files

0.8.1

2 files

0.8.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page