Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand Down
9 changes: 5 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ classifiers = [
"Topic :: Software Development :: Libraries",
"Topic :: Software Development :: Libraries :: Application Frameworks",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]


[tool.poetry.dependencies]
python = ">=3.9,<4.0"
python = ">=3.10,<4.0"
aio-pika = { version = ">=8.0", optional = true }
aiohttp = { version = ">=3.7", optional = true }
flask = { version = ">=2.0.0", optional = true }
Expand Down Expand Up @@ -69,17 +69,18 @@ standard-imghdr = "^3.13.0"
codecov = "^2.1.13"
mypy = "^1.15.0"
pre-commit = "~3.2.0"
aioresponses = "^0.7.4"
aiointercept = "^0.1.9"
asynctest = "^0.13.0"
deepdiff = "^8.0.1"
pytest = "^7.4.0"
pytest = "^9.1.1"
pytest-aiohttp = "^1.0.4"
pytest-cov = "^4.1.0"
pytest-mock = "^3.11.1"
responses = "^0.23.3"
respx = "^0.22.0"
types-requests = "^2.32.0.20241016"
jsonschema = "^4.25.1"
pytest-lazy-fixtures = "^1.4.0"

[build-system]
requires = ["poetry-core>=1.0.0"]
Expand Down
6 changes: 3 additions & 3 deletions tests/client/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import pytest
from aioresponses import aioresponses
from aiointercept import aiointercept


@pytest.fixture
def responses():
with aioresponses() as mocker:
async def aiointerceptor():
async with aiointercept(mock_external_urls=True) as mocker:
yield mocker
169 changes: 88 additions & 81 deletions tests/client/test_async_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

import pytest
import respx
from aioresponses import aioresponses
from aiointercept import aiointercept
from pytest_lazy_fixtures import lf

import pjrpc
from pjrpc.client.backend import aiohttp as aiohttp_backend
Expand All @@ -17,14 +18,14 @@ class Request(NamedTuple):
content: str

def __init__(self):
self.mocker = aioresponses()
self.mocker = aiointercept(mock_external_urls=True)

def __enter__(self):
self.mocker.__enter__()
async def __aenter__(self):
await self.mocker.__aenter__()
return self

def __exit__(self, exc_type, exc_val, exc_tb):
self.mocker.__exit__(exc_type, exc_val, exc_tb)
async def __aexit__(self, exc_type, exc_val, exc_tb):
await self.mocker.__aexit__(exc_type, exc_val, exc_tb)

def mock(self, method=None, url=None, status=None, content=None, json=None):
self.mocker.add(method=method, url=url, status=status, body=content, payload=json, repeat=True)
Expand All @@ -38,6 +39,12 @@ def requests(self):
]


@pytest.fixture()
async def aiohttp_mocker():
async with AioHttpMocker() as moker:
yield moker


class RespxMocker(respx.MockRouter):

def mock(self, method=None, url=None, status=None, content=None, json=None):
Expand All @@ -49,32 +56,36 @@ def requests(self):
return [request for request, response in self.calls]


@pytest.fixture()
async def respx_mocker():
async with RespxMocker() as moker:
yield moker


@pytest.mark.parametrize(
'Client, mocker', [
(aiohttp_backend.Client, AioHttpMocker),
(httpx_backend.AsyncClient, RespxMocker),
(aiohttp_backend.Client, lf('aiohttp_mocker')),
(httpx_backend.AsyncClient, lf('respx_mocker')),
],
)
async def test_call(Client, mocker):
test_url = 'http://test.com/api'

with mocker() as mock:
mock.mock(
'POST', test_url, status=200, json={
'jsonrpc': '2.0',
'id': 1,
'result': 'result',
},
)

client = Client(test_url)
mocker.mock(
'POST', test_url, status=200, json={
'jsonrpc': '2.0',
'id': 1,
'result': 'result',
},
)

async with Client(test_url) as client:
response = await client.send(pjrpc.Request(method='method', params=(1, 2), id=1))
assert response.id == 1
assert response.result == 'result'

assert mock.requests[0].url == test_url
assert json.loads(mock.requests[0].content) == {
assert mocker.requests[0].url == test_url
assert json.loads(mocker.requests[0].content) == {
'jsonrpc': '2.0',
'id': 1,
'method': 'method',
Expand All @@ -84,8 +95,8 @@ async def test_call(Client, mocker):
result = await client.call('method', arg1=1, arg2=2)
assert result == 'result'

assert mock.requests[1].url == test_url
assert json.loads(mock.requests[1].content) == {
assert mocker.requests[1].url == test_url
assert json.loads(mocker.requests[1].content) == {
'jsonrpc': '2.0',
'id': 1,
'method': 'method',
Expand All @@ -95,8 +106,8 @@ async def test_call(Client, mocker):
result = await client('method', 1, 2)
assert result == 'result'

assert mock.requests[2].url == test_url
assert json.loads(mock.requests[2].content) == {
assert mocker.requests[2].url == test_url
assert json.loads(mocker.requests[2].content) == {
'jsonrpc': '2.0',
'id': 1,
'method': 'method',
Expand All @@ -106,8 +117,8 @@ async def test_call(Client, mocker):
result = await client.proxy.method(1, 2)
assert result == 'result'

assert mock.requests[3].url == test_url
assert json.loads(mock.requests[3].content) == {
assert mocker.requests[3].url == test_url
assert json.loads(mocker.requests[3].content) == {
'jsonrpc': '2.0',
'id': 1,
'method': 'method',
Expand All @@ -117,31 +128,29 @@ async def test_call(Client, mocker):

@pytest.mark.parametrize(
'Client, mocker', [
(aiohttp_backend.Client, AioHttpMocker),
(httpx_backend.AsyncClient, RespxMocker),
(aiohttp_backend.Client, lf('aiohttp_mocker')),
(httpx_backend.AsyncClient, lf('respx_mocker')),
],
)
async def test_notify(Client, mocker):
test_url = 'http://test.com/api'

with mocker() as mock:
mock.mock('POST', test_url, status=200, content=' ')

client = Client(test_url)
mocker.mock('POST', test_url, status=200, content=' ')

async with Client(test_url) as client:
response = await client.send(pjrpc.Request(method='method', params=[1, 2]))
assert response is None
assert mock.requests[0].url == test_url
assert json.loads(mock.requests[0].content) == {
assert mocker.requests[0].url == test_url
assert json.loads(mocker.requests[0].content) == {
'jsonrpc': '2.0',
'method': 'method',
'params': [1, 2],
}

response = await client.notify('method', a=1, b=2)
assert response is None
assert mock.requests[1].url == test_url
assert json.loads(mock.requests[1].content) == {
assert mocker.requests[1].url == test_url
assert json.loads(mocker.requests[1].content) == {
'jsonrpc': '2.0',
'method': 'method',
'params': {'a': 1, 'b': 2},
Expand All @@ -150,31 +159,29 @@ async def test_notify(Client, mocker):

@pytest.mark.parametrize(
'Client, mocker', [
(aiohttp_backend.Client, AioHttpMocker),
(httpx_backend.AsyncClient, RespxMocker),
(aiohttp_backend.Client, lf('aiohttp_mocker')),
(httpx_backend.AsyncClient, lf('respx_mocker')),
],
)
async def test_batch(Client, mocker):
test_url = 'http://test.com/api'

with (mocker() as mock):
mock.mock(
'POST', test_url, status=200, json=[
{
'jsonrpc': '2.0',
'id': 1,
'result': 'result1',
},
{
'jsonrpc': '2.0',
'id': 2,
'result': 2,
},
],
)

client = Client(test_url)
mocker.mock(
'POST', test_url, status=200, json=[
{
'jsonrpc': '2.0',
'id': 1,
'result': 'result1',
},
{
'jsonrpc': '2.0',
'id': 2,
'result': 2,
},
],
)

async with Client(test_url) as client:
async with client.batch() as batch:
batch.send(pjrpc.Request(method='method1', params=[1, 2], id=1))
batch.send(pjrpc.Request(method='method2', params=[2, 3], id=2))
Expand All @@ -188,8 +195,8 @@ async def test_batch(Client, mocker):
assert result[1].id == 2
assert result[1].result == 2

assert mock.requests[0].url == test_url
assert json.loads(mock.requests[0].content) == [
assert mocker.requests[0].url == test_url
assert json.loads(mocker.requests[0].content) == [
{
'jsonrpc': '2.0',
'id': 1,
Expand All @@ -216,8 +223,8 @@ async def test_batch(Client, mocker):
result = batch.get_results()
assert result == ['result1', 2]

assert mock.requests[1].url == test_url
assert json.loads(mock.requests[1].content) == [
assert mocker.requests[1].url == test_url
assert json.loads(mocker.requests[1].content) == [
{
'jsonrpc': '2.0',
'id': 1,
Expand All @@ -239,8 +246,8 @@ async def test_batch(Client, mocker):
result = batch.get_results()
assert result == ['result1', 2]

assert mock.requests[2].url == test_url
assert json.loads(mock.requests[2].content) == [
assert mocker.requests[2].url == test_url
assert json.loads(mocker.requests[2].content) == [
{
'jsonrpc': '2.0',
'id': 1,
Expand All @@ -262,8 +269,8 @@ async def test_batch(Client, mocker):
result = batch.get_results()
assert result == ['result1', 2]

assert mock.requests[3].url == test_url
assert json.loads(mock.requests[3].content) == [
assert mocker.requests[3].url == test_url
assert json.loads(mocker.requests[3].content) == [
{
'jsonrpc': '2.0',
'id': 1,
Expand All @@ -278,17 +285,18 @@ async def test_batch(Client, mocker):
},
]

with mocker() as mock:
mock.mock('POST', test_url, status=200, content=' ')
mocker.mock('POST', test_url, status=200, content=' ')

async with Client(test_url) as client:
async with client.batch() as batch:
batch.notify('method1', 1, 2)
batch.notify('method2', 2, 3)

result = batch.get_response()
assert result is None

assert mock.requests[0].url == test_url
assert json.loads(mock.requests[0].content) == [
assert mocker.requests[4].url == test_url
assert json.loads(mocker.requests[4].content) == [
{
'jsonrpc': '2.0',
'method': 'method1',
Expand All @@ -304,24 +312,23 @@ async def test_batch(Client, mocker):

@pytest.mark.parametrize(
'Client, mocker', [
(aiohttp_backend.Client, AioHttpMocker),
(httpx_backend.AsyncClient, RespxMocker),
(aiohttp_backend.Client, lf('aiohttp_mocker')),
(httpx_backend.AsyncClient, lf('respx_mocker')),
],
)
async def test_context_manager(Client, mocker):
test_url = 'http://test.com/api'

with mocker() as mock:
mock.mock(
'POST', test_url, status=200, json={
'jsonrpc': '2.0',
'id': 1,
'result': 'result',
},
)
mocker.mock(
'POST', test_url, status=200, json={
'jsonrpc': '2.0',
'id': 1,
'result': 'result',
},
)

async with Client(test_url) as client:
response = await client.send(pjrpc.Request(method='method', params=(1, 2), id=1))
async with Client(test_url) as client:
response = await client.send(pjrpc.Request(method='method', params=(1, 2), id=1))

assert response.id == 1
assert response.result == 'result'
assert response.id == 1
assert response.result == 'result'
Loading
Loading