You've already forked bthlabs-jsonrpc
v1.1.0b1
This commit is contained in:
@@ -1,10 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# type: ignore
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from aiohttp.web import Request
|
||||
import pytest
|
||||
|
||||
from .fixtures import AsyncJSONCodec
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_request():
|
||||
def fake_request() -> mock.Mock:
|
||||
return mock.Mock(spec=Request)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def async_json_codec() -> AsyncJSONCodec:
|
||||
return AsyncJSONCodec()
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# type: ignore
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from unittest import mock
|
||||
|
||||
from bthlabs_jsonrpc_core import exceptions, serializer
|
||||
import pytest
|
||||
|
||||
from bthlabs_jsonrpc_aiohttp import executor
|
||||
from tests.fixtures import AsyncJSONCodec
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_can_call():
|
||||
def fake_can_call() -> mock.Mock:
|
||||
result = mock.AsyncMock()
|
||||
result.return_value = True
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def test_init(fake_request, fake_can_call):
|
||||
def test_init(fake_request: mock.Mock, fake_can_call: mock.Mock):
|
||||
# When
|
||||
result = executor.AioHttpExecutor(fake_request, fake_can_call)
|
||||
|
||||
@@ -24,7 +29,7 @@ def test_init(fake_request, fake_can_call):
|
||||
assert result.can_call == fake_can_call
|
||||
|
||||
|
||||
async def test_list_methods(fake_request, fake_can_call):
|
||||
async def test_list_methods(fake_request: mock.Mock, fake_can_call: mock.Mock):
|
||||
# Given
|
||||
the_executor = executor.AioHttpExecutor(fake_request, fake_can_call)
|
||||
|
||||
@@ -35,9 +40,10 @@ async def test_list_methods(fake_request, fake_can_call):
|
||||
assert result == ['system.list_methods']
|
||||
|
||||
|
||||
async def test_deserialize_data(fake_request, fake_can_call):
|
||||
async def test_deserialize_data(fake_request: mock.Mock,
|
||||
fake_can_call: mock.Mock):
|
||||
# Given
|
||||
fake_request.json.return_value = 'spam'
|
||||
fake_request.text.return_value = '"spam"'
|
||||
|
||||
the_executor = executor.AioHttpExecutor(fake_request, fake_can_call)
|
||||
|
||||
@@ -48,9 +54,28 @@ async def test_deserialize_data(fake_request, fake_can_call):
|
||||
assert result == 'spam'
|
||||
|
||||
|
||||
async def test_deserialize_data_error(fake_request, fake_can_call):
|
||||
async def test_deserialize_data_async_codec_decode(fake_request: mock.Mock,
|
||||
async_json_codec: AsyncJSONCodec,
|
||||
fake_can_call: mock.Mock):
|
||||
# Given
|
||||
fake_request.json.side_effect = RuntimeError('I HAZ FAIL')
|
||||
fake_request.text.return_value = '"spam"'
|
||||
|
||||
the_executor = executor.AioHttpExecutor(
|
||||
fake_request, fake_can_call, codec=async_json_codec,
|
||||
)
|
||||
|
||||
# When
|
||||
result = await the_executor.deserialize_data(fake_request)
|
||||
|
||||
# Then
|
||||
assert result == 'spam'
|
||||
|
||||
|
||||
async def test_deserialize_data_error(fake_request: mock.Mock,
|
||||
fake_can_call: mock.Mock):
|
||||
# Given
|
||||
error = RuntimeError('I HAZ FAIL')
|
||||
fake_request.text.side_effect = error
|
||||
|
||||
the_executor = executor.AioHttpExecutor(fake_request, fake_can_call)
|
||||
|
||||
@@ -59,11 +84,12 @@ async def test_deserialize_data_error(fake_request, fake_can_call):
|
||||
_ = await the_executor.deserialize_data(fake_request)
|
||||
except Exception as exception:
|
||||
assert isinstance(exception, exceptions.JSONRPCParseError)
|
||||
assert exception.__cause__ == error
|
||||
else:
|
||||
assert False, 'No exception raised?'
|
||||
|
||||
|
||||
def test_enrich_args(fake_request, fake_can_call):
|
||||
def test_enrich_args(fake_request: mock.Mock, fake_can_call: mock.Mock):
|
||||
# Given
|
||||
the_executor = executor.AioHttpExecutor(fake_request, fake_can_call)
|
||||
|
||||
@@ -74,7 +100,7 @@ def test_enrich_args(fake_request, fake_can_call):
|
||||
assert result == [fake_request, 'spam']
|
||||
|
||||
|
||||
async def test_before_call(fake_request, fake_can_call):
|
||||
async def test_before_call(fake_request: mock.Mock, fake_can_call: mock.Mock):
|
||||
# Given
|
||||
the_executor = executor.AioHttpExecutor(fake_request, fake_can_call)
|
||||
|
||||
@@ -87,7 +113,8 @@ async def test_before_call(fake_request, fake_can_call):
|
||||
)
|
||||
|
||||
|
||||
async def test_before_call_access_denied(fake_request, fake_can_call):
|
||||
async def test_before_call_access_denied(fake_request: mock.Mock,
|
||||
fake_can_call: mock.Mock):
|
||||
# Given
|
||||
fake_can_call.return_value = False
|
||||
|
||||
@@ -103,7 +130,9 @@ async def test_before_call_access_denied(fake_request, fake_can_call):
|
||||
|
||||
|
||||
@mock.patch('bthlabs_jsonrpc_core.registry.MethodRegistry.shared_registry')
|
||||
async def test_execute(mock_shared_registry, fake_request, fake_can_call):
|
||||
async def test_execute(mock_shared_registry: mock.Mock,
|
||||
fake_request: mock.Mock,
|
||||
fake_can_call: mock.Mock):
|
||||
# Given
|
||||
fake_method_registry = mock.Mock()
|
||||
fake_method_registry.get_handler.return_value = None
|
||||
@@ -129,7 +158,7 @@ async def test_execute(mock_shared_registry, fake_request, fake_can_call):
|
||||
},
|
||||
]
|
||||
|
||||
fake_request.json.return_value = batch
|
||||
fake_request.text.return_value = json.dumps(batch)
|
||||
|
||||
the_executor = executor.AioHttpExecutor(fake_request, fake_can_call)
|
||||
|
||||
|
||||
17
packages/bthlabs-jsonrpc-aiohttp/tests/fixtures.py
Normal file
17
packages/bthlabs-jsonrpc-aiohttp/tests/fixtures.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# type: ignore
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
|
||||
from bthlabs_jsonrpc_core import codecs
|
||||
|
||||
|
||||
class AsyncJSONCodec(codecs.JSONCodec):
|
||||
async def decode(self,
|
||||
payload: str | bytes,
|
||||
**decoder_kwargs) -> typing.Any:
|
||||
return super().decode(payload, **decoder_kwargs)
|
||||
|
||||
async def encode(self, payload: typing.Any, **encoder_kwargs) -> str:
|
||||
return super().encode(payload, **encoder_kwargs)
|
||||
@@ -1,10 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# type: ignore
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from aiohttp.test_utils import TestClient
|
||||
from aiohttp import web
|
||||
from bthlabs_jsonrpc_core import exceptions
|
||||
from bthlabs_jsonrpc_core import codecs, exceptions
|
||||
import pytest
|
||||
|
||||
from bthlabs_jsonrpc_aiohttp import views
|
||||
from bthlabs_jsonrpc_aiohttp.executor import AioHttpExecutor
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_aiohttp_executor() -> mock.Mock:
|
||||
return mock.Mock(spec=AioHttpExecutor)
|
||||
|
||||
|
||||
def test_init():
|
||||
@@ -13,6 +24,7 @@ def test_init():
|
||||
|
||||
# Then
|
||||
assert result.namespace is None
|
||||
assert result.codec == codecs.JSONCodec
|
||||
|
||||
|
||||
def test_init_with_namespace():
|
||||
@@ -23,7 +35,53 @@ def test_init_with_namespace():
|
||||
assert result.namespace == 'testing'
|
||||
|
||||
|
||||
async def test_can_call(fake_request):
|
||||
def test_init_with_codec(fake_custom_codec: mock.Mock):
|
||||
# When
|
||||
result = views.JSONRPCView(codec=fake_custom_codec)
|
||||
|
||||
# Then
|
||||
assert result.codec == fake_custom_codec
|
||||
|
||||
|
||||
async def test_get_executor(fake_request: mock.Mock):
|
||||
# Given
|
||||
view = views.JSONRPCView()
|
||||
|
||||
# When
|
||||
result = await view.get_executor(fake_request)
|
||||
|
||||
# Then
|
||||
assert isinstance(result, views.AioHttpExecutor) is True
|
||||
|
||||
|
||||
async def test_get_executor_dependency_calls(fake_aiohttp_executor: mock.Mock,
|
||||
fake_custom_codec: mock.Mock,
|
||||
fake_request: mock.Mock):
|
||||
# Given
|
||||
with mock.patch.object(views, 'AioHttpExecutor') as mock_aiohttp_executor:
|
||||
with mock.patch.object(views.JSONRPCView, 'get_codec') as mock_get_codec:
|
||||
mock_aiohttp_executor.return_value = fake_aiohttp_executor
|
||||
mock_get_codec.return_value = fake_custom_codec
|
||||
|
||||
view = views.JSONRPCView()
|
||||
|
||||
# When
|
||||
result = await view.get_executor(fake_request)
|
||||
|
||||
# Then
|
||||
assert result == fake_aiohttp_executor
|
||||
|
||||
mock_get_codec.assert_awaited_once_with(fake_request)
|
||||
|
||||
mock_aiohttp_executor.assert_called_once_with(
|
||||
fake_request,
|
||||
view.can_call,
|
||||
namespace=view.namespace,
|
||||
codec=fake_custom_codec,
|
||||
)
|
||||
|
||||
|
||||
async def test_can_call(fake_request: mock.Mock):
|
||||
# Given
|
||||
view = views.JSONRPCView()
|
||||
|
||||
@@ -34,7 +92,7 @@ async def test_can_call(fake_request):
|
||||
assert result is True
|
||||
|
||||
|
||||
async def test_view(aiohttp_client):
|
||||
async def test_view(aiohttp_client: TestClient):
|
||||
# Given
|
||||
view = views.JSONRPCView()
|
||||
|
||||
@@ -87,7 +145,7 @@ async def test_view(aiohttp_client):
|
||||
assert data == expected_result_data
|
||||
|
||||
|
||||
async def test_view_empty_response(aiohttp_client):
|
||||
async def test_view_empty_response(aiohttp_client: TestClient):
|
||||
# Given
|
||||
view = views.JSONRPCView()
|
||||
|
||||
@@ -111,7 +169,7 @@ async def test_view_empty_response(aiohttp_client):
|
||||
assert data == b''
|
||||
|
||||
|
||||
async def test_view_permission_denied(aiohttp_client):
|
||||
async def test_view_permission_denied(aiohttp_client: TestClient):
|
||||
# Given
|
||||
view = views.JSONRPCView()
|
||||
|
||||
@@ -146,3 +204,36 @@ async def test_view_permission_denied(aiohttp_client):
|
||||
},
|
||||
}
|
||||
assert data == expected_result_data
|
||||
|
||||
|
||||
async def test_view_async_codec_encode(async_json_codec: mock.Mock,
|
||||
aiohttp_client: TestClient):
|
||||
# Given
|
||||
mock_codec = mock.Mock(return_value=async_json_codec)
|
||||
|
||||
view = views.JSONRPCView(codec=mock_codec)
|
||||
|
||||
app = web.Application()
|
||||
app.router.add_post('/', view)
|
||||
|
||||
client = await aiohttp_client(app)
|
||||
|
||||
call = {
|
||||
'jsonrpc': '2.0',
|
||||
'id': 'test',
|
||||
'method': 'system.list_methods',
|
||||
}
|
||||
|
||||
# When
|
||||
response = await client.post('/', json=call)
|
||||
|
||||
# Then
|
||||
assert response.status == 200
|
||||
|
||||
data = await response.json()
|
||||
expected_result_data = {
|
||||
'jsonrpc': '2.0',
|
||||
'id': 'test',
|
||||
'result': ['system.list_methods'],
|
||||
}
|
||||
assert data == expected_result_data
|
||||
|
||||
Reference in New Issue
Block a user