Skip to content

Commit b8ad022

Browse files
baywetCopilot
andcommitted
test(coverage): add reference and reader edge tests
Add focused tests for CopyReferences, OpenApiSecurityRequirement deserialization, and small uncovered exception/helper types without broad fixture duplication. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 25fb628 commit b8ad022

5 files changed

Lines changed: 271 additions & 0 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
using System.Text.Json.Nodes;
4+
using Microsoft.OpenApi.Reader;
5+
using Microsoft.OpenApi.Reader.V2;
6+
using Microsoft.OpenApi.YamlReader;
7+
using SharpYaml.Serialization;
8+
using Xunit;
9+
10+
namespace Microsoft.OpenApi.Readers.Tests.V2Tests;
11+
12+
[Collection("DefaultSettings")]
13+
public class OpenApiSecurityRequirementTests
14+
{
15+
[Fact]
16+
public void LoadSecurityRequirementResolvesScopesForKnownSchemes()
17+
{
18+
var node = LoadYamlNode(
19+
"""
20+
petstore_auth:
21+
- write:pets
22+
- read:pets
23+
""");
24+
var hostDocument = new OpenApiDocument
25+
{
26+
Components = new OpenApiComponents
27+
{
28+
SecuritySchemes = new Dictionary<string, IOpenApiSecurityScheme>
29+
{
30+
["petstore_auth"] = new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2 }
31+
}
32+
}
33+
};
34+
var context = new ParsingContext(new OpenApiDiagnostic());
35+
36+
var requirement = OpenApiV2Deserializer.LoadSecurityRequirement(node, hostDocument, context);
37+
38+
var resolvedScheme = Assert.Single(requirement);
39+
Assert.Equal("petstore_auth", resolvedScheme.Key.Reference.Id);
40+
Assert.Equal(["write:pets", "read:pets"], resolvedScheme.Value);
41+
Assert.Empty(context.Diagnostic.Errors);
42+
}
43+
44+
[Fact]
45+
public void LoadSecurityRequirementCreatesUnresolvedReferenceWhenSchemeIsMissing()
46+
{
47+
var node = LoadYamlNode(
48+
"""
49+
petstore_auth:
50+
- write:pets
51+
""");
52+
var hostDocument = new OpenApiDocument();
53+
var context = new ParsingContext(new OpenApiDiagnostic());
54+
55+
var requirement = OpenApiV2Deserializer.LoadSecurityRequirement(node, hostDocument, context);
56+
57+
var unresolvedScheme = Assert.Single(requirement);
58+
Assert.Equal("petstore_auth", unresolvedScheme.Key.Reference.Id);
59+
Assert.True(unresolvedScheme.Key.UnresolvedReference);
60+
Assert.Equal(["write:pets"], unresolvedScheme.Value);
61+
Assert.Empty(context.Diagnostic.Errors);
62+
}
63+
64+
private static JsonNode LoadYamlNode(string yaml)
65+
{
66+
using var reader = new StringReader(yaml);
67+
var yamlStream = new YamlStream();
68+
yamlStream.Load(reader);
69+
return yamlStream.Documents[0].RootNode.ToJsonNode();
70+
}
71+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using Xunit;
3+
4+
namespace Microsoft.OpenApi.Tests.Exceptions;
5+
6+
public class OpenApiWriterExceptionTests
7+
{
8+
[Fact]
9+
public void DefaultConstructorUsesTheGenericWriterMessage()
10+
{
11+
var exception = new OpenApiWriterException();
12+
13+
Assert.Equal(SRResource.OpenApiWriterExceptionGenericError, exception.Message);
14+
Assert.Null(exception.InnerException);
15+
}
16+
17+
[Fact]
18+
public void ConstructorPreservesMessageAndInnerException()
19+
{
20+
var innerException = new InvalidOperationException("boom");
21+
22+
var exception = new OpenApiWriterException("writer failed", innerException);
23+
24+
Assert.Equal("writer failed", exception.Message);
25+
Assert.Same(innerException, exception.InnerException);
26+
}
27+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using Xunit;
2+
3+
namespace Microsoft.OpenApi.Tests.Models;
4+
5+
public class OpenApiReferenceErrorTests
6+
{
7+
[Fact]
8+
public void ConstructorCopiesMessageAndPointerFromException()
9+
{
10+
var exception = new OpenApiException("Reference could not be resolved")
11+
{
12+
Pointer = "#/components/schemas/Pet"
13+
};
14+
15+
var error = new OpenApiReferenceError(exception);
16+
17+
Assert.Equal(exception.Message, error.Message);
18+
Assert.Equal(exception.Pointer, error.Pointer);
19+
Assert.Null(error.Reference);
20+
}
21+
22+
[Fact]
23+
public void ConstructorStoresTheReferenceThatFailedResolution()
24+
{
25+
var reference = new BaseOpenApiReference
26+
{
27+
Id = "Pet",
28+
Type = ReferenceType.Schema
29+
};
30+
31+
var error = new OpenApiReferenceError(reference, "Missing component");
32+
33+
Assert.Equal("Missing component", error.Message);
34+
Assert.Equal(string.Empty, error.Pointer);
35+
Assert.Same(reference, error.Reference);
36+
}
37+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Collections.Generic;
2+
using System.Text.Json.Nodes;
3+
using Xunit;
4+
using Microsoft.OpenApi.Reader;
5+
6+
namespace Microsoft.OpenApi.Tests.Reader;
7+
8+
public class AnyListFieldMapParameterTests
9+
{
10+
[Fact]
11+
public void ConstructorStoresPropertyDelegates()
12+
{
13+
var schema = new OpenApiSchema { Type = JsonSchemaType.Array };
14+
var values = new List<JsonNode> { JsonValue.Create("value")! };
15+
var owner = new TestOwner { Schema = schema };
16+
var parameter = new AnyListFieldMapParameter<TestOwner>(
17+
static current => current.Values,
18+
static (current, currentValues) => current.Values = currentValues,
19+
static current => current.Schema);
20+
21+
parameter.PropertySetter(owner, values);
22+
23+
Assert.Same(values, parameter.PropertyGetter(owner));
24+
Assert.NotNull(parameter.SchemaGetter);
25+
Assert.Same(schema, parameter.SchemaGetter(owner));
26+
}
27+
28+
private sealed class TestOwner
29+
{
30+
public List<JsonNode> Values { get; set; } = [];
31+
public OpenApiSchema Schema { get; set; } = new();
32+
}
33+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
using System.Collections.Generic;
2+
using System.Net.Http;
3+
using Xunit;
4+
5+
namespace Microsoft.OpenApi.Tests.Services;
6+
7+
public class CopyReferencesTests
8+
{
9+
[Fact]
10+
public void VisitCopiesResolvedReferenceTargetsIntoMatchingComponentCollections()
11+
{
12+
var callback = new OpenApiCallback
13+
{
14+
PathItems = new Dictionary<RuntimeExpression, IOpenApiPathItem>
15+
{
16+
[RuntimeExpression.Build("{$request.body#/callbackUrl}")] = new OpenApiPathItem
17+
{
18+
Operations = new Dictionary<HttpMethod, OpenApiOperation>
19+
{
20+
[HttpMethod.Post] = new()
21+
{
22+
Responses = new OpenApiResponses
23+
{
24+
["200"] = new OpenApiResponse { Description = "ok" }
25+
}
26+
}
27+
}
28+
}
29+
}
30+
};
31+
var link = new OpenApiLink { OperationId = "getUser" };
32+
var requestBody = new OpenApiRequestBody
33+
{
34+
Required = true,
35+
Content = new Dictionary<string, IOpenApiMediaType>
36+
{
37+
["application/json"] = new OpenApiMediaType()
38+
}
39+
};
40+
var securityScheme = new OpenApiSecurityScheme
41+
{
42+
Type = SecuritySchemeType.ApiKey,
43+
Name = "api-key",
44+
In = ParameterLocation.Header
45+
};
46+
47+
var source = new OpenApiDocument
48+
{
49+
Components = new OpenApiComponents
50+
{
51+
Callbacks = new Dictionary<string, IOpenApiCallback> { ["callback"] = callback },
52+
Links = new Dictionary<string, IOpenApiLink> { ["link"] = link },
53+
RequestBodies = new Dictionary<string, IOpenApiRequestBody> { ["body"] = requestBody },
54+
SecuritySchemes = new Dictionary<string, IOpenApiSecurityScheme> { ["scheme"] = securityScheme }
55+
}
56+
};
57+
source.RegisterComponents();
58+
var target = new OpenApiDocument();
59+
var visitor = new CopyReferences(target);
60+
61+
visitor.Visit((IOpenApiReferenceHolder)new OpenApiCallbackReference("callback", source));
62+
visitor.Visit((IOpenApiReferenceHolder)new OpenApiLinkReference("link", source));
63+
visitor.Visit((IOpenApiReferenceHolder)new OpenApiRequestBodyReference("body", source));
64+
visitor.Visit((IOpenApiReferenceHolder)new OpenApiSecuritySchemeReference("scheme", source));
65+
66+
Assert.Same(callback, Assert.Single(visitor.Components.Callbacks).Value);
67+
Assert.Same(link, Assert.Single(visitor.Components.Links).Value);
68+
Assert.Same(requestBody, Assert.Single(visitor.Components.RequestBodies).Value);
69+
Assert.Same(securityScheme, Assert.Single(visitor.Components.SecuritySchemes).Value);
70+
71+
Assert.NotNull(target.Components);
72+
Assert.NotNull(target.Components.Callbacks);
73+
Assert.NotNull(target.Components.Links);
74+
Assert.NotNull(target.Components.RequestBodies);
75+
Assert.NotNull(target.Components.SecuritySchemes);
76+
}
77+
78+
[Fact]
79+
public void VisitCopiesSchemaTargetsOnceAndIgnoresMissingReferences()
80+
{
81+
var schema = new OpenApiSchema { Type = JsonSchemaType.Object };
82+
var source = new OpenApiDocument
83+
{
84+
Components = new OpenApiComponents
85+
{
86+
Schemas = new Dictionary<string, IOpenApiSchema> { ["Pet"] = schema }
87+
}
88+
};
89+
source.RegisterComponents();
90+
var visitor = new CopyReferences(new OpenApiDocument());
91+
92+
visitor.Visit((IOpenApiReferenceHolder)new OpenApiLinkReference("missing", source));
93+
94+
var schemaReference = new OpenApiSchemaReference("Pet", source);
95+
visitor.Visit((IOpenApiSchema)schemaReference);
96+
visitor.Visit((IOpenApiSchema)schemaReference);
97+
98+
Assert.Null(visitor.Components.Links);
99+
var copiedSchema = Assert.Single(visitor.Components.Schemas);
100+
Assert.Equal("Pet", copiedSchema.Key);
101+
Assert.Same(schema, copiedSchema.Value);
102+
}
103+
}

0 commit comments

Comments
 (0)