Coverage for tests / test_dump_json_fast_path.py: 100%

28 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-04-06 01:24 +0000

1from unittest.mock import patch 1adbc

2 

3from fastapi import FastAPI 1adbc

4from fastapi.responses import JSONResponse 1adbc

5from fastapi.testclient import TestClient 1adbc

6from pydantic import BaseModel 1adbc

7 

8 

9class Item(BaseModel): 1adbc

10 name: str 1abc

11 price: float 1abc

12 

13 

14app = FastAPI() 1adbc

15 

16 

17@app.get("/default") 1adbc

18def get_default() -> Item: 1adbc

19 return Item(name="widget", price=9.99) 1efgh

20 

21 

22@app.get("/explicit", response_class=JSONResponse) 1adbc

23def get_explicit() -> Item: 1adbc

24 return Item(name="widget", price=9.99) 1ijkl

25 

26 

27client = TestClient(app) 1adbc

28 

29 

30def test_default_response_class_skips_json_dumps(): 1adbc

31 """When no response_class is set, the fast path serializes directly to 

32 JSON bytes via Pydantic's dump_json and never calls json.dumps.""" 

33 with patch( 1efgh

34 "starlette.responses.json.dumps", wraps=__import__("json").dumps 

35 ) as mock_dumps: 

36 response = client.get("/default") 1efgh

37 assert response.status_code == 200 1efgh

38 assert response.json() == {"name": "widget", "price": 9.99} 1efgh

39 mock_dumps.assert_not_called() 1efgh

40 

41 

42def test_explicit_response_class_uses_json_dumps(): 1adbc

43 """When response_class is explicitly set to JSONResponse, the normal path 

44 is used and json.dumps is called via JSONResponse.render().""" 

45 with patch( 1ijkl

46 "starlette.responses.json.dumps", wraps=__import__("json").dumps 

47 ) as mock_dumps: 

48 response = client.get("/explicit") 1ijkl

49 assert response.status_code == 200 1ijkl

50 assert response.json() == {"name": "widget", "price": 9.99} 1ijkl

51 mock_dumps.assert_called_once() 1ijkl