Skip to content

Commit f159bed

Browse files
committed
Add unit tests for circular references and remove it from the sample
1 parent d3d5982 commit f159bed

File tree

4 files changed

+138
-117
lines changed

4 files changed

+138
-117
lines changed

src/OpenApi/sample/Endpoints/MapCircularSchemaEndpoints.cs

Lines changed: 0 additions & 43 deletions
This file was deleted.

src/OpenApi/sample/Program.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System.Globalization;
55
using System.Text.Json.Serialization;
6-
using Sample.Endpoints;
76
using Sample.Transformers;
87

98
var builder = WebApplication.CreateBuilder(args);
@@ -36,8 +35,6 @@
3635
return Task.CompletedTask;
3736
});
3837
});
39-
builder.Services.AddOpenApi("circular1");
40-
builder.Services.AddOpenApi("circular2");
4138
builder.Services.AddOpenApi("controllers");
4239
builder.Services.AddOpenApi("responses");
4340
builder.Services.AddOpenApi("forms");
@@ -62,8 +59,6 @@
6259
app.MapSwaggerUi();
6360
}
6461

65-
app.MapCircularEndpoints1();
66-
app.MapCircularEndpoints2();
6762
app.MapFormEndpoints();
6863
app.MapV1Endpoints();
6964
app.MapV2Endpoints();

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentLocalizationTests.VerifyOpenApiDocumentIsInvariant.verified.txt

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -11,44 +11,6 @@
1111
}
1212
],
1313
"paths": {
14-
"/circular1/model": {
15-
"get": {
16-
"tags": [
17-
"Sample"
18-
],
19-
"responses": {
20-
"200": {
21-
"description": "OK",
22-
"content": {
23-
"application/json": {
24-
"schema": {
25-
"$ref": "#/components/schemas/CircularModel1"
26-
}
27-
}
28-
}
29-
}
30-
}
31-
}
32-
},
33-
"/circular2/model": {
34-
"get": {
35-
"tags": [
36-
"Sample"
37-
],
38-
"responses": {
39-
"200": {
40-
"description": "OK",
41-
"content": {
42-
"application/json": {
43-
"schema": {
44-
"$ref": "#/components/schemas/CircularModel2"
45-
}
46-
}
47-
}
48-
}
49-
}
50-
}
51-
},
5214
"/forms/form-file": {
5315
"post": {
5416
"tags": [
@@ -1630,28 +1592,6 @@
16301592
}
16311593
}
16321594
},
1633-
"CircularModel1": {
1634-
"type": "object",
1635-
"properties": {
1636-
"referenced": {
1637-
"$ref": "#/components/schemas/ReferencedModel"
1638-
},
1639-
"self": {
1640-
"$ref": "#/components/schemas/CircularModel1"
1641-
}
1642-
}
1643-
},
1644-
"CircularModel2": {
1645-
"type": "object",
1646-
"properties": {
1647-
"self": {
1648-
"$ref": "#/components/schemas/CircularModel2"
1649-
},
1650-
"referenced": {
1651-
"$ref": "#/components/schemas/ReferencedModel"
1652-
}
1653-
}
1654-
},
16551595
"CityResponse": {
16561596
"type": "object",
16571597
"properties": {
@@ -2270,15 +2210,6 @@
22702210
}
22712211
}
22722212
},
2273-
"ReferencedModel": {
2274-
"type": "object",
2275-
"properties": {
2276-
"id": {
2277-
"type": "integer",
2278-
"format": "int32"
2279-
}
2280-
}
2281-
},
22822213
"RefProfile": {
22832214
"required": [
22842215
"user"
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.AspNetCore.Builder;
5+
using Microsoft.AspNetCore.Routing;
6+
7+
public partial class OpenApiSchemaServiceTests : OpenApiDocumentServiceTestBase
8+
{
9+
[Fact]
10+
public async Task SchemaReferences_HandlesCircularReferencesRegardlessOfPropertyOrder_SelfFirst()
11+
{
12+
var builder = CreateBuilder();
13+
builder.MapPost("/", (DirectCircularModelSelfFirst dto) => { });
14+
15+
// Assert
16+
await VerifyOpenApiDocument(builder, document =>
17+
{
18+
var schema = document.Components.Schemas["DirectCircularModelSelfFirst"];
19+
Assert.Equal(JsonSchemaType.Object, schema.Type);
20+
Assert.Collection(schema.Properties,
21+
property =>
22+
{
23+
Assert.Equal("self", property.Key);
24+
var reference = Assert.IsType<OpenApiSchemaReference>(property.Value);
25+
Assert.Equal("#/components/schemas/DirectCircularModelSelfFirst", reference.Reference.ReferenceV3);
26+
},
27+
property =>
28+
{
29+
Assert.Equal("referenced", property.Key);
30+
var reference = Assert.IsType<OpenApiSchemaReference>(property.Value);
31+
});
32+
33+
// Verify that it does not result in an empty schema for a referenced schema
34+
var referencedSchema = document.Components.Schemas["ReferencedModel"];
35+
Assert.NotEmpty(referencedSchema.Properties);
36+
var idProperty = Assert.Single(referencedSchema.Properties);
37+
Assert.Equal("id", idProperty.Key);
38+
var idPropertySchema = Assert.IsType<OpenApiSchema>(idProperty.Value);
39+
Assert.Equal(JsonSchemaType.Integer, idPropertySchema.Type);
40+
});
41+
}
42+
43+
[Fact]
44+
public async Task SchemaReferences_HandlesCircularReferencesRegardlessOfPropertyOrder_SelfLast()
45+
{
46+
var builder = CreateBuilder();
47+
builder.MapPost("/", (DirectCircularModelSelfLast dto) => { });
48+
49+
await VerifyOpenApiDocument(builder, document =>
50+
{
51+
var schema = document.Components.Schemas["DirectCircularModelSelfLast"];
52+
Assert.Equal(JsonSchemaType.Object, schema.Type);
53+
Assert.Collection(schema.Properties,
54+
property =>
55+
{
56+
Assert.Equal("referenced", property.Key);
57+
var reference = Assert.IsType<OpenApiSchemaReference>(property.Value);
58+
},
59+
property =>
60+
{
61+
Assert.Equal("self", property.Key);
62+
var reference = Assert.IsType<OpenApiSchemaReference>(property.Value);
63+
Assert.Equal("#/components/schemas/DirectCircularModelSelfLast", reference.Reference.ReferenceV3);
64+
});
65+
66+
// Verify that it does not result in an empty schema for a referenced schema
67+
var referencedSchema = document.Components.Schemas["ReferencedModel"];
68+
Assert.NotEmpty(referencedSchema.Properties);
69+
var idProperty = Assert.Single(referencedSchema.Properties);
70+
Assert.Equal("id", idProperty.Key);
71+
var idPropertySchema = Assert.IsType<OpenApiSchema>(idProperty.Value);
72+
Assert.Equal(JsonSchemaType.Integer, idPropertySchema.Type);
73+
});
74+
}
75+
76+
[Fact]
77+
public async Task SchemaReferences_HandlesCircularReferencesRegardlessOfPropertyOrder_MultipleSelf()
78+
{
79+
var builder = CreateBuilder();
80+
builder.MapPost("/", (DirectCircularModelMultiple dto) => { });
81+
82+
await VerifyOpenApiDocument(builder, document =>
83+
{
84+
var schema = document.Components.Schemas["DirectCircularModelMultiple"];
85+
Assert.Equal(JsonSchemaType.Object, schema.Type);
86+
Assert.Collection(schema.Properties,
87+
property =>
88+
{
89+
Assert.Equal("selfFirst", property.Key);
90+
var reference = Assert.IsType<OpenApiSchemaReference>(property.Value);
91+
Assert.Equal("#/components/schemas/DirectCircularModelMultiple", reference.Reference.ReferenceV3);
92+
},
93+
property =>
94+
{
95+
Assert.Equal("referenced", property.Key);
96+
var reference = Assert.IsType<OpenApiSchemaReference>(property.Value);
97+
},
98+
property =>
99+
{
100+
Assert.Equal("selfLast", property.Key);
101+
var reference = Assert.IsType<OpenApiSchemaReference>(property.Value);
102+
Assert.Equal("#/components/schemas/DirectCircularModelMultiple", reference.Reference.ReferenceV3);
103+
});
104+
105+
// Verify that it does not result in an empty schema for a referenced schema
106+
var referencedSchema = document.Components.Schemas["ReferencedModel"];
107+
Assert.NotEmpty(referencedSchema.Properties);
108+
var idProperty = Assert.Single(referencedSchema.Properties);
109+
Assert.Equal("id", idProperty.Key);
110+
var idPropertySchema = Assert.IsType<OpenApiSchema>(idProperty.Value);
111+
Assert.Equal(JsonSchemaType.Integer, idPropertySchema.Type);
112+
});
113+
}
114+
115+
private class DirectCircularModelSelfFirst
116+
{
117+
public DirectCircularModelSelfFirst Self { get; set; } = null!;
118+
public ReferencedModel Referenced { get; set; } = null!;
119+
}
120+
121+
private class DirectCircularModelSelfLast
122+
{
123+
public ReferencedModel Referenced { get; set; } = null!;
124+
public DirectCircularModelSelfLast Self { get; set; } = null!;
125+
}
126+
127+
private class DirectCircularModelMultiple
128+
{
129+
public DirectCircularModelMultiple SelfFirst { get; set; } = null!;
130+
public ReferencedModel Referenced { get; set; } = null!;
131+
public DirectCircularModelMultiple SelfLast { get; set; } = null!;
132+
}
133+
134+
private class ReferencedModel
135+
{
136+
public int Id { get; set; }
137+
}
138+
}

0 commit comments

Comments
 (0)