Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test with FastAPI TestClient returns 422 status code

Tags:

python

fastapi

I try to test an endpoint with the TestClient from FastAPI (which is the Scarlett TestClient basically).

The response code is always 422 Unprocessable Entity.

This is my current Code:

from typing import Dict, Optional

from fastapi import APIRouter
from pydantic import BaseModel

router = APIRouter()


class CreateRequest(BaseModel):
    number: int
    ttl: Optional[float] = None


@router.post("/create")
async def create_users(body: CreateRequest) -> Dict:
    return {
        "msg": f"{body.number} Users are created"
    }

As you can see I'm also passing the application/json header to the client to avoid a potential error.

And this is my Test:

from fastapi.testclient import TestClient
from metusa import app


def test_create_50_users():
    client = TestClient(app)
    client.headers["Content-Type"] = "application/json"

    body = {
        "number": 50,
        "ttl": 2.0
    }
    response = client.post('/v1/users/create', data=body)

    assert response.status_code == 200
    assert response.json() == {"msg": "50 Users created"}

I also found this error message in the Response Object

b'{"detail":[{"loc":["body",0],"msg":"Expecting value: line 1 column 1 (char 0)","type":"value_error.jsondecode","ctx":{"msg":"Expecting value","doc":"number=50&ttl=2.0","pos":0,"lineno":1,"colno":1}}]}'

Thank you for your support and time!

like image 631
JBDev Avatar asked Sep 11 '20 21:09

JBDev


People also ask

How do I fix Error 422?

The 422 Unprocessable Entityerror code can be caused by malware, security problems with the site, or a script not running properly. The fix is usually to contact your hosting provider and/or developer for assistance. If you're a website owner, knowing all types of HTTP status codes is critical.

How do you write test cases in FastAPI?

Using TestClient Import TestClient . Create a TestClient by passing your FastAPI application to it. Create functions with a name that starts with test_ (this is standard pytest conventions). Use the TestClient object the same way as you do with requests .


1 Answers

You don't need to set headers manualy. You can use json argument insteed of data in client.post method.

def test_create_50_users():
    client = TestClient(router)

    body = {
        "number": 50,
        "ttl": 2.0
    }
    response = client.post('/create', json=body)

If you still want to use data attribute, you need to use json.dumps

def test_create_50_users():
    client = TestClient(router)
    client.headers["Content-Type"] = "application/json"

    body = {
        "number": 50,
        "ttl": 2.0
    }
    response = client.post('/create', data=json.dumps(body))
like image 120
Alexey Sherchenkov Avatar answered Oct 24 '22 23:10

Alexey Sherchenkov