Maintained fork of aioresponses with aiohttp compatibility fixes
Project description
aioresponses-ng
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=Falsemeans the response is used once (repeat=1does the same). - Use
repeat=nto repeat a response n times. - Use
repeat=Trueto 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ee168f7bccfcc7990a995fcabf42bb84dd42faafaa30497c7108b093214633f
|
|
| MD5 |
243ab59b31640efd18740544d737565f
|
|
| BLAKE2b-256 |
646f6e317e805995b704894d9fc90ca63a87a567daf567e58db138659bf0abdc
|
Provenance
The following attestation bundles were made for aioresponses_ng-0.8.2.tar.gz:
Publisher:
release.yml on MountainGod2/aioresponses-ng
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aioresponses_ng-0.8.2.tar.gz -
Subject digest:
0ee168f7bccfcc7990a995fcabf42bb84dd42faafaa30497c7108b093214633f - Sigstore transparency entry: 2082204677
- Sigstore integration time:
-
Permalink:
MountainGod2/aioresponses-ng@812969c019f598769a6f24780fd4137f0477ce20 -
Branch / Tag:
refs/tags/v0.8.2 - Owner: https://github.com/MountainGod2
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@812969c019f598769a6f24780fd4137f0477ce20 -
Trigger Event:
release
-
Statement type:
File details
Details for the file aioresponses_ng-0.8.2-py3-none-any.whl.
File metadata
- Download URL: aioresponses_ng-0.8.2-py3-none-any.whl
- Upload date:
- Size: 10.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9de28a0de0ad289c6317b56da2f81c846643e4b9c2fde32023c1509064fbb72d
|
|
| MD5 |
db28a509281cecaf58ac3bcaa97533f2
|
|
| BLAKE2b-256 |
a79d4ad5aebee5771ce0822135b6daaa21b45f44043b15eb1b7afc2faaeabf1c
|
Provenance
The following attestation bundles were made for aioresponses_ng-0.8.2-py3-none-any.whl:
Publisher:
release.yml on MountainGod2/aioresponses-ng
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aioresponses_ng-0.8.2-py3-none-any.whl -
Subject digest:
9de28a0de0ad289c6317b56da2f81c846643e4b9c2fde32023c1509064fbb72d - Sigstore transparency entry: 2082204687
- Sigstore integration time:
-
Permalink:
MountainGod2/aioresponses-ng@812969c019f598769a6f24780fd4137f0477ce20 -
Branch / Tag:
refs/tags/v0.8.2 - Owner: https://github.com/MountainGod2
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@812969c019f598769a6f24780fd4137f0477ce20 -
Trigger Event:
release
-
Statement type: