Skip to content

Commit b67aa2a

Browse files
committed
tests: Add test case for nullable references
This is somewhat undefined behavior [1][2], however, it worked until openapi-core 0.15.x. Demonstrate this, pending a fix. [1] https://stackoverflow.com/a/48114924/613428 [2] OAI/OpenAPI-Specification#1368 Signed-off-by: Stephen Finucane <[email protected]>
1 parent 56863fb commit b67aa2a

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
openapi: "3.0.0"
2+
info:
3+
version: "0.1"
4+
title: OpenAPI specification with nullable refs
5+
paths:
6+
/people/{personID}:
7+
get:
8+
summary: Show a person
9+
parameters:
10+
- name: personID
11+
in: path
12+
required: true
13+
description: The ID of the person to retrieve
14+
schema:
15+
type: string
16+
format: uuid
17+
responses:
18+
default:
19+
description: Expected response to a valid request
20+
content:
21+
application/json:
22+
schema:
23+
$ref: '#/components/schemas/Person'
24+
components:
25+
schemas:
26+
Person:
27+
x-model: Person
28+
type: object
29+
required:
30+
- id
31+
- name
32+
properties:
33+
id:
34+
description: The ID of the person.
35+
type: string
36+
format: uuid
37+
name:
38+
description: The full name of the person.
39+
type: string
40+
user:
41+
description: The associated user account, if any.
42+
nullable: true
43+
allOf:
44+
- $ref: '#/components/schemas/User'
45+
User:
46+
x-model: User
47+
type: object
48+
required:
49+
- id
50+
- username
51+
properties:
52+
id:
53+
description: The ID of the user.
54+
type: string
55+
format: uuid
56+
username:
57+
description: The username of the user.
58+
type: string
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from dataclasses import is_dataclass
2+
import json
3+
import uuid
4+
5+
import pytest
6+
7+
from openapi_core.testing import MockRequest
8+
from openapi_core.testing import MockResponse
9+
from openapi_core.validation.response import openapi_v30_response_validator
10+
11+
12+
@pytest.fixture(scope="class")
13+
def spec(factory):
14+
return factory.spec_from_file("data/v3.0/nullable_ref.yaml")
15+
16+
17+
class TestNullableRefs:
18+
@pytest.mark.xfail(message="The nullable attribute should be respected")
19+
def test_with_null_value(self, spec):
20+
person = {
21+
"id": str(uuid.uuid4()),
22+
"name": "Joe Bloggs",
23+
"user": None,
24+
}
25+
request = MockRequest("", "get", f"/people/{person['id']}")
26+
response = MockResponse(json.dumps(person))
27+
28+
result = openapi_v30_response_validator.validate(
29+
spec, request, response
30+
)
31+
32+
assert not result.errors
33+
assert is_dataclass(result.data)
34+
assert result.data.__class__.__name__ == "Person"
35+
assert result.data.id == uuid.UUID(person["id"])
36+
assert result.data.name == person["name"]
37+
assert result.data.user is None
38+
39+
def test_with_non_null_value(self, spec):
40+
person = {
41+
"id": str(uuid.uuid4()),
42+
"name": "Joe Bloggs",
43+
"user": {
44+
"id": str(uuid.uuid4()),
45+
"username": "joebloggs",
46+
},
47+
}
48+
request = MockRequest("", "get", f"/people/{person['id']}")
49+
response = MockResponse(json.dumps(person))
50+
51+
result = openapi_v30_response_validator.validate(
52+
spec, request, response
53+
)
54+
55+
assert not result.errors
56+
assert is_dataclass(result.data)
57+
assert result.data.__class__.__name__ == "Person"
58+
assert result.data.id == uuid.UUID(person["id"])
59+
assert result.data.name == person["name"]
60+
assert result.data.user is not None
61+
assert result.data.user.id == uuid.UUID(person["user"]["id"])
62+
assert result.data.user.username == person["user"]["username"]

0 commit comments

Comments
 (0)