fastapi

Форк
0
/
test_multi_body_errors.py 
237 строк · 8.0 Кб
1
from decimal import Decimal
2
from typing import List
3

4
from dirty_equals import IsDict, IsOneOf
5
from fastapi import FastAPI
6
from fastapi.testclient import TestClient
7
from fastapi.utils import match_pydantic_error_url
8
from pydantic import BaseModel, condecimal
9

10
app = FastAPI()
11

12

13
class Item(BaseModel):
14
    name: str
15
    age: condecimal(gt=Decimal(0.0))  # type: ignore
16

17

18
@app.post("/items/")
19
def save_item_no_body(item: List[Item]):
20
    return {"item": item}
21

22

23
client = TestClient(app)
24

25

26
def test_put_correct_body():
27
    response = client.post("/items/", json=[{"name": "Foo", "age": 5}])
28
    assert response.status_code == 200, response.text
29
    assert response.json() == {
30
        "item": [
31
            {
32
                "name": "Foo",
33
                "age": IsOneOf(
34
                    5,
35
                    # TODO: remove when deprecating Pydantic v1
36
                    "5",
37
                ),
38
            }
39
        ]
40
    }
41

42

43
def test_jsonable_encoder_requiring_error():
44
    response = client.post("/items/", json=[{"name": "Foo", "age": -1.0}])
45
    assert response.status_code == 422, response.text
46
    assert response.json() == IsDict(
47
        {
48
            "detail": [
49
                {
50
                    "type": "greater_than",
51
                    "loc": ["body", 0, "age"],
52
                    "msg": "Input should be greater than 0",
53
                    "input": -1.0,
54
                    "ctx": {"gt": 0},
55
                    "url": match_pydantic_error_url("greater_than"),
56
                }
57
            ]
58
        }
59
    ) | IsDict(
60
        # TODO: remove when deprecating Pydantic v1
61
        {
62
            "detail": [
63
                {
64
                    "ctx": {"limit_value": 0.0},
65
                    "loc": ["body", 0, "age"],
66
                    "msg": "ensure this value is greater than 0",
67
                    "type": "value_error.number.not_gt",
68
                }
69
            ]
70
        }
71
    )
72

73

74
def test_put_incorrect_body_multiple():
75
    response = client.post("/items/", json=[{"age": "five"}, {"age": "six"}])
76
    assert response.status_code == 422, response.text
77
    assert response.json() == IsDict(
78
        {
79
            "detail": [
80
                {
81
                    "type": "missing",
82
                    "loc": ["body", 0, "name"],
83
                    "msg": "Field required",
84
                    "input": {"age": "five"},
85
                    "url": match_pydantic_error_url("missing"),
86
                },
87
                {
88
                    "type": "decimal_parsing",
89
                    "loc": ["body", 0, "age"],
90
                    "msg": "Input should be a valid decimal",
91
                    "input": "five",
92
                    "url": match_pydantic_error_url("decimal_parsing"),
93
                },
94
                {
95
                    "type": "missing",
96
                    "loc": ["body", 1, "name"],
97
                    "msg": "Field required",
98
                    "input": {"age": "six"},
99
                    "url": match_pydantic_error_url("missing"),
100
                },
101
                {
102
                    "type": "decimal_parsing",
103
                    "loc": ["body", 1, "age"],
104
                    "msg": "Input should be a valid decimal",
105
                    "input": "six",
106
                    "url": match_pydantic_error_url("decimal_parsing"),
107
                },
108
            ]
109
        }
110
    ) | IsDict(
111
        # TODO: remove when deprecating Pydantic v1
112
        {
113
            "detail": [
114
                {
115
                    "loc": ["body", 0, "name"],
116
                    "msg": "field required",
117
                    "type": "value_error.missing",
118
                },
119
                {
120
                    "loc": ["body", 0, "age"],
121
                    "msg": "value is not a valid decimal",
122
                    "type": "type_error.decimal",
123
                },
124
                {
125
                    "loc": ["body", 1, "name"],
126
                    "msg": "field required",
127
                    "type": "value_error.missing",
128
                },
129
                {
130
                    "loc": ["body", 1, "age"],
131
                    "msg": "value is not a valid decimal",
132
                    "type": "type_error.decimal",
133
                },
134
            ]
135
        }
136
    )
137

138

139
def test_openapi_schema():
140
    response = client.get("/openapi.json")
141
    assert response.status_code == 200, response.text
142
    assert response.json() == {
143
        "openapi": "3.1.0",
144
        "info": {"title": "FastAPI", "version": "0.1.0"},
145
        "paths": {
146
            "/items/": {
147
                "post": {
148
                    "responses": {
149
                        "200": {
150
                            "description": "Successful Response",
151
                            "content": {"application/json": {"schema": {}}},
152
                        },
153
                        "422": {
154
                            "description": "Validation Error",
155
                            "content": {
156
                                "application/json": {
157
                                    "schema": {
158
                                        "$ref": "#/components/schemas/HTTPValidationError"
159
                                    }
160
                                }
161
                            },
162
                        },
163
                    },
164
                    "summary": "Save Item No Body",
165
                    "operationId": "save_item_no_body_items__post",
166
                    "requestBody": {
167
                        "content": {
168
                            "application/json": {
169
                                "schema": {
170
                                    "title": "Item",
171
                                    "type": "array",
172
                                    "items": {"$ref": "#/components/schemas/Item"},
173
                                }
174
                            }
175
                        },
176
                        "required": True,
177
                    },
178
                }
179
            }
180
        },
181
        "components": {
182
            "schemas": {
183
                "Item": {
184
                    "title": "Item",
185
                    "required": ["name", "age"],
186
                    "type": "object",
187
                    "properties": {
188
                        "name": {"title": "Name", "type": "string"},
189
                        "age": IsDict(
190
                            {
191
                                "title": "Age",
192
                                "anyOf": [
193
                                    {"exclusiveMinimum": 0.0, "type": "number"},
194
                                    {"type": "string"},
195
                                ],
196
                            }
197
                        )
198
                        | IsDict(
199
                            # TODO: remove when deprecating Pydantic v1
200
                            {
201
                                "title": "Age",
202
                                "exclusiveMinimum": 0.0,
203
                                "type": "number",
204
                            }
205
                        ),
206
                    },
207
                },
208
                "ValidationError": {
209
                    "title": "ValidationError",
210
                    "required": ["loc", "msg", "type"],
211
                    "type": "object",
212
                    "properties": {
213
                        "loc": {
214
                            "title": "Location",
215
                            "type": "array",
216
                            "items": {
217
                                "anyOf": [{"type": "string"}, {"type": "integer"}]
218
                            },
219
                        },
220
                        "msg": {"title": "Message", "type": "string"},
221
                        "type": {"title": "Error Type", "type": "string"},
222
                    },
223
                },
224
                "HTTPValidationError": {
225
                    "title": "HTTPValidationError",
226
                    "type": "object",
227
                    "properties": {
228
                        "detail": {
229
                            "title": "Detail",
230
                            "type": "array",
231
                            "items": {"$ref": "#/components/schemas/ValidationError"},
232
                        }
233
                    },
234
                },
235
            }
236
        },
237
    }
238

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.