diff --git a/docs/sanic/testing.rst b/docs/sanic/testing.rst index 67506edc..0cf3ff40 100644 --- a/docs/sanic/testing.rst +++ b/docs/sanic/testing.rst @@ -58,6 +58,36 @@ More information about the available arguments to `httpx` can be found [in the documentation for `httpx `_. +Additionally, Sanic has an asynchronous testing client. The difference is that the async client will not stand up an +instance of your application, but will instead reach inside it using ASGI. All listeners and middleware are still +executed. + +.. code-block:: python + @pytest.mark.asyncio + async def test_index_returns_200(): + request, response = await app.asgi_client.put('/') + assert response.status == 200 +.. note:: + + Whenever one of the test clients run, you can test your app instance to determine if it is in testing mode: + `app.test_mode`. + +Additionally, Sanic has an asynchronous testing client. The difference is that the async client will not stand up an +instance of your application, but will instead reach inside it using ASGI. All listeners and middleware are still +executed. + +.. code-block:: python + + @pytest.mark.asyncio + async def test_index_returns_200(): + request, response = await app.asgi_client.put('/') + assert response.status == 200 + +.. note:: + + Whenever one of the test clients run, you can test your app instance to determine if it is in testing mode: + `app.test_mode`. + Using a random port ------------------- diff --git a/sanic/app.py b/sanic/app.py index 5c805874..25139e1b 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -90,6 +90,7 @@ class Sanic: self.named_response_middleware = {} # Register alternative method names self.go_fast = self.run + self.test_mode = False @property def loop(self): diff --git a/sanic/testing.py b/sanic/testing.py index 36233e70..faabdfd1 100644 --- a/sanic/testing.py +++ b/sanic/testing.py @@ -22,6 +22,14 @@ class SanicTestClient: self.port = port self.host = host + @app.listener("after_server_start") + def _start_test_mode(sanic, *args, **kwargs): + sanic.test_mode = True + + @app.listener("before_server_end") + def _end_test_mode(sanic, *args, **kwargs): + sanic.test_mode = False + def get_new_session(self): return httpx.AsyncClient(verify=False) @@ -209,6 +217,14 @@ class SanicASGITestClient(httpx.AsyncClient): def _collect_request(request): self.last_request = request + @app.listener("after_server_start") + def _start_test_mode(sanic, *args, **kwargs): + sanic.test_mode = True + + @app.listener("before_server_end") + def _end_test_mode(sanic, *args, **kwargs): + sanic.test_mode = False + app.request_middleware.appendleft(_collect_request) async def request(self, method, url, gather_request=True, *args, **kwargs): diff --git a/tests/test_app.py b/tests/test_app.py index ab7da76d..c7791394 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -222,3 +222,28 @@ def test_handle_request_with_nested_sanic_exception(app, monkeypatch, caplog): def test_app_name_required(): with pytest.deprecated_call(): Sanic() + + +def test_app_has_test_mode_sync(): + app = Sanic("test") + + @app.get("/") + def handler(request): + assert request.app.test_mode + return text("test") + + _, response = app.test_client.get("/") + assert response.status == 200 + + +# @pytest.mark.asyncio +# async def test_app_has_test_mode_async(): +# app = Sanic("test") + +# @app.get("/") +# async def handler(request): +# assert request.app.test_mode +# return text("test") + +# _, response = await app.asgi_client.get("/") +# assert response.status == 200