Coverage for tests / test_additional_responses_union_duplicate_anyof.py: 100%

19 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-02-12 18:15 +0000

1""" 

2Regression test: Ensure app-level responses with Union models and content/examples 

3don't accumulate duplicate $ref entries in anyOf arrays. 

4See https://github.com/fastapi/fastapi/pull/14463 

5""" 

6 

7from typing import Union 1abcd

8 

9from fastapi import FastAPI 1abcd

10from fastapi.testclient import TestClient 1abcd

11from inline_snapshot import snapshot 1abcd

12from pydantic import BaseModel 1abcd

13 

14 

15class ModelA(BaseModel): 1abcd

16 a: str 1abcd

17 

18 

19class ModelB(BaseModel): 1abcd

20 b: str 1abcd

21 

22 

23app = FastAPI( 1abcd

24 responses={ 

25 500: { 

26 "model": Union[ModelA, ModelB], 

27 "content": {"application/json": {"examples": {"Case A": {"value": "a"}}}}, 

28 } 

29 } 

30) 

31 

32 

33@app.get("/route1") 1abcd

34async def route1(): 1abcd

35 pass # pragma: no cover 

36 

37 

38@app.get("/route2") 1abcd

39async def route2(): 1abcd

40 pass # pragma: no cover 

41 

42 

43client = TestClient(app) 1abcd

44 

45 

46def test_openapi_schema(): 1abcd

47 response = client.get("/openapi.json") 1efg

48 assert response.status_code == 200, response.text 1efg

49 assert response.json() == snapshot( 1efg

50 { 

51 "openapi": "3.1.0", 

52 "info": {"title": "FastAPI", "version": "0.1.0"}, 

53 "paths": { 

54 "/route1": { 

55 "get": { 

56 "summary": "Route1", 

57 "operationId": "route1_route1_get", 

58 "responses": { 

59 "200": { 

60 "description": "Successful Response", 

61 "content": {"application/json": {"schema": {}}}, 

62 }, 

63 "500": { 

64 "description": "Internal Server Error", 

65 "content": { 

66 "application/json": { 

67 "schema": { 

68 "anyOf": [ 

69 {"$ref": "#/components/schemas/ModelA"}, 

70 {"$ref": "#/components/schemas/ModelB"}, 

71 ], 

72 "title": "Response 500 Route1 Route1 Get", 

73 }, 

74 "examples": {"Case A": {"value": "a"}}, 

75 } 

76 }, 

77 }, 

78 }, 

79 } 

80 }, 

81 "/route2": { 

82 "get": { 

83 "summary": "Route2", 

84 "operationId": "route2_route2_get", 

85 "responses": { 

86 "200": { 

87 "description": "Successful Response", 

88 "content": {"application/json": {"schema": {}}}, 

89 }, 

90 "500": { 

91 "description": "Internal Server Error", 

92 "content": { 

93 "application/json": { 

94 "schema": { 

95 "anyOf": [ 

96 {"$ref": "#/components/schemas/ModelA"}, 

97 {"$ref": "#/components/schemas/ModelB"}, 

98 ], 

99 "title": "Response 500 Route2 Route2 Get", 

100 }, 

101 "examples": {"Case A": {"value": "a"}}, 

102 } 

103 }, 

104 }, 

105 }, 

106 } 

107 }, 

108 }, 

109 "components": { 

110 "schemas": { 

111 "ModelA": { 

112 "properties": {"a": {"type": "string", "title": "A"}}, 

113 "type": "object", 

114 "required": ["a"], 

115 "title": "ModelA", 

116 }, 

117 "ModelB": { 

118 "properties": {"b": {"type": "string", "title": "B"}}, 

119 "type": "object", 

120 "required": ["b"], 

121 "title": "ModelB", 

122 }, 

123 } 

124 }, 

125 } 

126 )