125 lines
4.2 KiB
Markdown
125 lines
4.2 KiB
Markdown
# Test Clients
|
|
|
|
There are three different test clients available to you, each of them presents different capabilities.
|
|
|
|
## Regular sync client: `SanicTestClient`
|
|
|
|
The `SanicTestClient` runs an actual version of the Sanic Server on your local network to run its tests. Each time it calls an endpoint it will spin up a version of the application and bind it to a socket on the host OS. Then, it will use `httpx` to make calls directly to that application.
|
|
|
|
This is the typical way that Sanic applications are tested.
|
|
|
|
.. column::
|
|
|
|
Once installing Sanic Testing, the regular `SanicTestClient` can be used without further setup. This is because Sanic does the leg work for you under the hood.
|
|
|
|
.. column::
|
|
|
|
```python
|
|
app.test_client.get("/path/to/endpoint")
|
|
```
|
|
|
|
.. column::
|
|
|
|
However, you may find it desirable to instantiate the client yourself.
|
|
|
|
.. column::
|
|
|
|
```python
|
|
from sanic_testing.testing import SanicTestClient
|
|
|
|
test_client = SanicTestClient(app)
|
|
test_client.get("/path/to/endpoint")
|
|
```
|
|
|
|
.. column::
|
|
|
|
A third option for starting the test client is to use the `TestManager`. This is a convenience object that sets up both the `SanicTestClient` and the `SanicASGITestClient`.
|
|
|
|
.. column::
|
|
|
|
```python
|
|
from sanic_testing import TestManager
|
|
|
|
mgr = TestManager(app)
|
|
app.test_client.get("/path/to/endpoint")
|
|
# or
|
|
mgr.test_client.get("/path/to/endpoint")
|
|
```
|
|
|
|
You can make a request by using one of the following methods
|
|
|
|
- `SanicTestClient.get`
|
|
- `SanicTestClient.post`
|
|
- `SanicTestClient.put`
|
|
- `SanicTestClient.patch`
|
|
- `SanicTestClient.delete`
|
|
- `SanicTestClient.options`
|
|
- `SanicTestClient.head`
|
|
- `SanicTestClient.websocket`
|
|
- `SanicTestClient.request`
|
|
|
|
You can use these methods *almost* identically as you would when using `httpx`. Any argument that you would pass to `httpx` will be accepted, **with one caveat**: If you are using `test_client.request` and want to manually specify the HTTP method, you should use: `http_method`:
|
|
|
|
```python
|
|
test_client.request("/path/to/endpoint", http_method="get")
|
|
```
|
|
|
|
## ASGI async client: `SanicASGITestClient`
|
|
|
|
Unlike the `SanicTestClient` that spins up a server on every request, the `SanicASGITestClient` does not. Instead it makes use of the `httpx` library to execute Sanic as an ASGI application to reach inside and execute the route handlers.
|
|
|
|
.. column::
|
|
|
|
This test client provides all of the same methods and generally works as the `SanicTestClient`. The only difference is that you will need to add an `await` to each call:
|
|
|
|
.. column::
|
|
|
|
```python
|
|
await app.test_client.get("/path/to/endpoint")
|
|
```
|
|
|
|
The `SanicASGITestClient` can be used in the exact same three ways as the `SanicTestClient`.
|
|
|
|
|
|
.. note::
|
|
|
|
The `SanicASGITestClient` does not need to only be used with ASGI applications. The same way that the `SanicTestClient` does not need to only test sync endpoints. Both of these clients are capable of testing *any* Sanic application.
|
|
|
|
|
|
## Persistent service client: `ReusableClient`
|
|
|
|
This client works under a similar premise as the `SanicTestClient` in that it stands up an instance of your application and makes real HTTP requests to it. However, unlike the `SanicTestClient`, when using the `ReusableClient` you control the lifecycle of the application.
|
|
|
|
That means that every request **does not** start a new web server. Instead you will start the server and stop it as needed and can make multiple requests to the same running instance.
|
|
|
|
.. column::
|
|
|
|
Unlike the other two clients, you **must** instantiate this client for use:
|
|
|
|
.. column::
|
|
|
|
```python
|
|
from sanic_testing.reusable import ReusableClient
|
|
|
|
client = ReusableClient(app)
|
|
```
|
|
|
|
.. column::
|
|
|
|
Once created, you will use the client inside of a context manager. Once outside of the scope of the manager, the server will shutdown.
|
|
|
|
.. column::
|
|
|
|
```python
|
|
from sanic_testing.reusable import ReusableClient
|
|
|
|
def test_multiple_endpoints_on_same_server(app):
|
|
client = ReusableClient(app)
|
|
with client:
|
|
_, response = client.get("/path/to/1")
|
|
assert response.status == 200
|
|
|
|
_, response = client.get("/path/to/2")
|
|
assert response.status == 200
|
|
```
|