From 9aeabcf9155ffacc7b4fd336e141e0cc3e05cdf2 Mon Sep 17 00:00:00 2001 From: Ollie Copping Date: Mon, 22 Nov 2021 10:13:00 +0000 Subject: [PATCH] Adding tests for `HTTPAdapter` (#52) * Initial commit (create test script) * Reworked how the server is set up into it's own function to allow for easier testing * Remove KeyboardInterrupt exception * Added tests for HTTPAdapter --- tests/adapters/test_httpadapter.py | 72 ++++++++++++++++++++++++++++++ tickit/adapters/httpadapter.py | 25 ++++++----- 2 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 tests/adapters/test_httpadapter.py diff --git a/tests/adapters/test_httpadapter.py b/tests/adapters/test_httpadapter.py new file mode 100644 index 000000000..076257656 --- /dev/null +++ b/tests/adapters/test_httpadapter.py @@ -0,0 +1,72 @@ +from typing import Iterable + +import pytest +from aiohttp import web +from mock import Mock +from mock.mock import create_autospec, patch + +from tickit.adapters.httpadapter import HTTPAdapter +from tickit.adapters.interpreters.endpoints.http_endpoint import HTTPEndpoint +from tickit.core.device import Device + + +@pytest.fixture +def mock_device() -> Device: + return create_autospec(Device) + + +@pytest.fixture +def mock_raise_interrupt(): + async def raise_interrupt(): + return False + + return Mock(raise_interrupt) + + +class MockAdapter(HTTPAdapter): + + device: Device + + @HTTPEndpoint.get("/mock_endpoint") + async def mock_endpoint(request: web.Request) -> web.Response: + return web.Response(text="test") + + +@pytest.fixture +def http_adapter() -> HTTPAdapter: + http_adapter = HTTPAdapter() + return http_adapter + + +def test_http_adapter_constructor(): + HTTPAdapter() + + +@pytest.fixture +def patch_asyncio_event_wait() -> Iterable[Mock]: + with patch( + "tickit.core.components.device_simulation.asyncio.Event.wait", autospec=True + ) as mock: + yield mock + + +@pytest.mark.asyncio +async def test_http_adapter_run_forever_method( + http_adapter, + mock_device: Device, + mock_raise_interrupt: Mock, + patch_asyncio_event_wait: Mock, +): + await http_adapter.run_forever(mock_device, mock_raise_interrupt) + + patch_asyncio_event_wait.assert_awaited_once() + + +@pytest.mark.asyncio +async def test_http_adapter_endpoints(): + + adapter = MockAdapter() + + resp = await list(adapter.endpoints())[0].handler() + + assert resp.text == "test" diff --git a/tickit/adapters/httpadapter.py b/tickit/adapters/httpadapter.py index 03f254c57..bc073c5d9 100644 --- a/tickit/adapters/httpadapter.py +++ b/tickit/adapters/httpadapter.py @@ -30,21 +30,24 @@ async def run_forever( ) -> None: """Runs the server continously.""" await super().run_forever(device, raise_interrupt) - LOGGER.debug(f"Starting HTTP server... {self}") - app = web.Application() - app.add_routes(list(self.endpoints())) - runner = web.AppRunner(app) - await runner.setup() - site = web.TCPSite(runner, host=self.host, port=self.port) - await site.start() + + await self._start_server() + try: await asyncio.Event().wait() - except KeyboardInterrupt: - pass finally: # TODO: This doesn't work yet due to asyncio's own exception handler - await app.shutdown() - await app.cleanup() + await self.app.shutdown() + await self.app.cleanup() + + async def _start_server(self): + LOGGER.debug(f"Starting HTTP server... {self}") + self.app = web.Application() + self.app.add_routes(list(self.endpoints())) + runner = web.AppRunner(self.app) + await runner.setup() + site = web.TCPSite(runner, host=self.host, port=self.port) + await site.start() def endpoints(self) -> Iterable[RouteDef]: """Returns list of endpoints.