Coverage for tests / test_security_scopes_sub_dependency.py: 100%

38 statements  

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

1# Ref: https://github.com/fastapi/fastapi/discussions/6024#discussioncomment-8541913 

2 

3 

4from typing import Annotated 1efgh

5 

6import pytest 1efgh

7from fastapi import Depends, FastAPI, Security 1efgh

8from fastapi.security import SecurityScopes 1efgh

9from fastapi.testclient import TestClient 1efgh

10 

11 

12@pytest.fixture(name="call_counts") 1efgh

13def call_counts_fixture(): 1efgh

14 return { 1ijkl

15 "get_db_session": 0, 

16 "get_current_user": 0, 

17 "get_user_me": 0, 

18 "get_user_items": 0, 

19 } 

20 

21 

22@pytest.fixture(name="app") 1efgh

23def app_fixture(call_counts: dict[str, int]): 1efgh

24 def get_db_session(): 1ijkl

25 call_counts["get_db_session"] += 1 1abcd

26 return f"db_session_{call_counts['get_db_session']}" 1abcd

27 

28 def get_current_user( 1ijkl

29 security_scopes: SecurityScopes, 

30 db_session: Annotated[str, Depends(get_db_session)], 

31 ): 

32 call_counts["get_current_user"] += 1 1abcd

33 return { 1abcd

34 "user": f"user_{call_counts['get_current_user']}", 

35 "scopes": security_scopes.scopes, 

36 "db_session": db_session, 

37 } 

38 

39 def get_user_me( 1ijkl

40 current_user: Annotated[dict, Security(get_current_user, scopes=["me"])], 

41 ): 

42 call_counts["get_user_me"] += 1 1abcd

43 return { 1abcd

44 "user_me": f"user_me_{call_counts['get_user_me']}", 

45 "current_user": current_user, 

46 } 

47 

48 def get_user_items( 1ijkl

49 user_me: Annotated[dict, Depends(get_user_me)], 

50 ): 

51 call_counts["get_user_items"] += 1 1abcd

52 return { 1abcd

53 "user_items": f"user_items_{call_counts['get_user_items']}", 

54 "user_me": user_me, 

55 } 

56 

57 app = FastAPI() 1ijkl

58 

59 @app.get("/") 1ijkl

60 def path_operation( 1ijkl

61 user_me: Annotated[dict, Depends(get_user_me)], 

62 user_items: Annotated[dict, Security(get_user_items, scopes=["items"])], 

63 ): 

64 return { 1abcd

65 "user_me": user_me, 

66 "user_items": user_items, 

67 } 

68 

69 return app 1ijkl

70 

71 

72@pytest.fixture(name="client") 1efgh

73def client_fixture(app: FastAPI): 1efgh

74 return TestClient(app) 1ijkl

75 

76 

77def test_security_scopes_sub_dependency_caching( 1efgh

78 client: TestClient, call_counts: dict[str, int] 

79): 

80 response = client.get("/") 1abcd

81 

82 assert response.status_code == 200 1abcd

83 assert call_counts["get_db_session"] == 1 1abcd

84 assert call_counts["get_current_user"] == 2 1abcd

85 assert call_counts["get_user_me"] == 2 1abcd

86 assert call_counts["get_user_items"] == 1 1abcd

87 assert response.json() == { 1abcd

88 "user_me": { 

89 "user_me": "user_me_1", 

90 "current_user": { 

91 "user": "user_1", 

92 "scopes": ["me"], 

93 "db_session": "db_session_1", 

94 }, 

95 }, 

96 "user_items": { 

97 "user_items": "user_items_1", 

98 "user_me": { 

99 "user_me": "user_me_2", 

100 "current_user": { 

101 "user": "user_2", 

102 "scopes": ["items", "me"], 

103 "db_session": "db_session_1", 

104 }, 

105 }, 

106 }, 

107 }