From f352c1610d94c9abe8d052e4b62587e1d25da886 Mon Sep 17 00:00:00 2001 From: Justin Yoo Date: Mon, 31 Aug 2020 15:52:28 +0900 Subject: [PATCH] Fix OpenApiPayloadAttributeExtension #107 #112 #113 --- .../DummyHttpTrigger.cs | 3 +- .../DummyHttpTrigger.cs | 3 +- .../OpenApiPayloadAttributeExtensions.cs | 2 +- .../Extensions/TypeExtensions.cs | 39 +++++++++ .../Visitors/DictionaryObjectTypeVisitor.cs | 15 ++-- .../Visitors/ListObjectTypeVisitor.cs | 17 ++-- .../Visitors/NullableObjectTypeVisitor.cs | 4 +- .../Visitors/TypeVisitor.cs | 28 +------ .../OpenApiPayloadAttributeExtensionsTests.cs | 82 +++++++++++++++++++ .../Extensions/TypeExtensionsTests.cs | 13 +++ .../DictionaryObjectTypeVisitorTests.cs | 29 ++++--- .../Visitors/ListObjectTypeVisitorTests.cs | 37 +++++---- 12 files changed, 201 insertions(+), 71 deletions(-) create mode 100644 test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Extensions/OpenApiPayloadAttributeExtensionsTests.cs diff --git a/samples/Aliencube.AzureFunctions.FunctionAppV3IoC/DummyHttpTrigger.cs b/samples/Aliencube.AzureFunctions.FunctionAppV3IoC/DummyHttpTrigger.cs index c41396b..628ade5 100644 --- a/samples/Aliencube.AzureFunctions.FunctionAppV3IoC/DummyHttpTrigger.cs +++ b/samples/Aliencube.AzureFunctions.FunctionAppV3IoC/DummyHttpTrigger.cs @@ -31,8 +31,8 @@ public DummyHttpTrigger(IDummyHttpService service) [OpenApiParameter(name: "name", In = ParameterLocation.Query, Required = true, Type = typeof(string), Summary = "Dummy name", Description = "Dummy name", Visibility = OpenApiVisibilityType.Important)] [OpenApiParameter(name: "switch", In = ParameterLocation.Path, Required = true, Type = typeof(StringEnum), Summary = "Dummy switch", Description = "Dummy switch", Visibility = OpenApiVisibilityType.Important)] [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(List), Summary = "List of the dummy responses", Description = "This returns the list of dummy responses")] + [OpenApiResponseWithBody(statusCode: HttpStatusCode.BadRequest, contentType: "application/json", bodyType: typeof(string), Summary = "Invalid switch", Description = "Switch parameter is not valid")] [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.NotFound, Summary = "Name not found", Description = "Name parameter is not found")] - [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.BadRequest, Summary = "Invalid switch", Description = "Switch parameter is not valid")] public async Task GetDummies( [HttpTrigger(AuthorizationLevel.Function, "GET", Route = "dummies")] HttpRequest req, ILogger log) @@ -65,6 +65,7 @@ public async Task AddDummy( [OpenApiOperation(operationId: "updateDummies", tags: new[] { "dummy" }, Summary = "Updates a list of dummies", Description = "This updates a list of dummies.", Visibility = OpenApiVisibilityType.Advanced)] [OpenApiRequestBody(contentType: "application/json", bodyType: typeof(DummyListModel), Required = true, Description = "Dummy list model")] [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(List), Summary = "Dummy response", Description = "This returns the dummy response")] + [OpenApiResponseWithBody(statusCode: HttpStatusCode.BadRequest, contentType: "application/json", bodyType: typeof(List), Summary = "Invalid switch", Description = "Switch parameter is not valid")] public async Task UpdateDummies( [HttpTrigger(AuthorizationLevel.Function, "PUT", Route = "dummies")] HttpRequest req, ILogger log) diff --git a/samples/Aliencube.AzureFunctions.FunctionAppV3Static/DummyHttpTrigger.cs b/samples/Aliencube.AzureFunctions.FunctionAppV3Static/DummyHttpTrigger.cs index 960ec06..2b177e8 100644 --- a/samples/Aliencube.AzureFunctions.FunctionAppV3Static/DummyHttpTrigger.cs +++ b/samples/Aliencube.AzureFunctions.FunctionAppV3Static/DummyHttpTrigger.cs @@ -22,8 +22,8 @@ public static class DummyHttpTrigger [OpenApiParameter(name: "name", In = ParameterLocation.Query, Required = true, Type = typeof(string), Summary = "Dummy name", Description = "Dummy name", Visibility = OpenApiVisibilityType.Important)] [OpenApiParameter(name: "switch", In = ParameterLocation.Path, Required = true, Type = typeof(StringEnum), Summary = "Dummy switch", Description = "Dummy switch", Visibility = OpenApiVisibilityType.Important)] [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(List), Summary = "List of the dummy responses", Description = "This returns the list of dummy responses")] + [OpenApiResponseWithBody(statusCode: HttpStatusCode.BadRequest, contentType: "application/json", bodyType: typeof(string), Summary = "Invalid switch", Description = "Switch parameter is not valid")] [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.NotFound, Summary = "Name not found", Description = "Name parameter is not found")] - [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.BadRequest, Summary = "Invalid switch", Description = "Switch parameter is not valid")] public static async Task GetDummies( [HttpTrigger(AuthorizationLevel.Function, "GET", Route = "dummies")] HttpRequest req, ILogger log) @@ -56,6 +56,7 @@ public static async Task AddDummy( [OpenApiOperation(operationId: "updateDummies", tags: new[] { "dummy" }, Summary = "Updates a list of dummies", Description = "This updates a list of dummies.", Visibility = OpenApiVisibilityType.Advanced)] [OpenApiRequestBody(contentType: "application/json", bodyType: typeof(DummyListModel), Required = true, Description = "Dummy list model")] [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(List), Summary = "Dummy response", Description = "This returns the dummy response")] + [OpenApiResponseWithBody(statusCode: HttpStatusCode.BadRequest, contentType: "application/json", bodyType: typeof(List), Summary = "Invalid switch", Description = "Switch parameter is not valid")] public static async Task UpdateDummies( [HttpTrigger(AuthorizationLevel.Function, "PUT", Route = "dummies")] HttpRequest req, ILogger log) diff --git a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Extensions/OpenApiPayloadAttributeExtensions.cs b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Extensions/OpenApiPayloadAttributeExtensions.cs index 1efe304..99d967e 100644 --- a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Extensions/OpenApiPayloadAttributeExtensions.cs +++ b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Extensions/OpenApiPayloadAttributeExtensions.cs @@ -40,7 +40,7 @@ public static OpenApiMediaType ToOpenApiMediaType(this T attribute, NamingStr var schema = collection.PayloadVisit(type, namingStrategy); // For array and dictionary object, the reference has already been added by the visitor. - if (!type.IsOpenApiArray() && !type.IsOpenApiDictionary()) + if (type.IsReferentialType() && !type.IsOpenApiNullable() && !type.IsOpenApiArray() && !type.IsOpenApiDictionary()) { var reference = new OpenApiReference() { diff --git a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Extensions/TypeExtensions.cs b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Extensions/TypeExtensions.cs index 266435f..9ba2a50 100644 --- a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Extensions/TypeExtensions.cs +++ b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Extensions/TypeExtensions.cs @@ -68,6 +68,45 @@ public static bool IsSimpleType(this Type type) } } + + /// + /// Checks whether the type can be referenced or not. + /// + /// Type to check. + /// Returns True, if the type can be referenced; otherwise returns False. + public static bool IsReferentialType(this Type type) + { + var @enum = Type.GetTypeCode(type); + var isReferential = @enum == TypeCode.Object; + + if (type == typeof(Guid)) + { + isReferential = false; + } + if (type == typeof(DateTime)) + { + isReferential = false; + } + if (type == typeof(DateTimeOffset)) + { + isReferential = false; + } + if (type.IsOpenApiNullable()) + { + isReferential = false; + } + if (type.IsUnflaggedEnumType()) + { + isReferential = false; + } + if (type.IsJObjectType()) + { + isReferential = false; + } + + return isReferential; + } + /// /// Checks whether the given type is Json.NET related , or not. /// diff --git a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/DictionaryObjectTypeVisitor.cs b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/DictionaryObjectTypeVisitor.cs index 4eaaf08..c62b816 100644 --- a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/DictionaryObjectTypeVisitor.cs +++ b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/DictionaryObjectTypeVisitor.cs @@ -124,17 +124,20 @@ public override OpenApiSchema PayloadVisit(Type type, NamingStrategy namingStrat var schema = this.PayloadVisit(dataType: "object", dataFormat: null); // Gets the schema for the underlying type. - var underlyingType = type.GetGenericArguments()[1]; + var underlyingType = type.GetUnderlyingType(); var properties = this.VisitorCollection.PayloadVisit(underlyingType, namingStrategy); // Adds the reference to the schema for the underlying type. - var reference = new OpenApiReference() + if (underlyingType.IsReferentialType()) { - Type = ReferenceType.Schema, - Id = underlyingType.GetOpenApiReferenceId(isDictionary: false, isList: false, namingStrategy) - }; + var reference = new OpenApiReference() + { + Type = ReferenceType.Schema, + Id = underlyingType.GetOpenApiReferenceId(isDictionary: false, isList: false, namingStrategy) + }; - properties.Reference = reference; + properties.Reference = reference; + } schema.AdditionalProperties = properties; diff --git a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/ListObjectTypeVisitor.cs b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/ListObjectTypeVisitor.cs index 1f7bc31..37aaff0 100644 --- a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/ListObjectTypeVisitor.cs +++ b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/ListObjectTypeVisitor.cs @@ -117,7 +117,7 @@ public override OpenApiSchema ParameterVisit(Type type, NamingStrategy namingStr { var schema = this.ParameterVisit(dataType: "array", dataFormat: null); - var underlyingType = type.GetElementType() ?? type.GetGenericArguments()[0]; + var underlyingType = type.GetUnderlyingType(); var items = this.VisitorCollection.ParameterVisit(underlyingType, namingStrategy); schema.Items = items; @@ -139,17 +139,20 @@ public override OpenApiSchema PayloadVisit(Type type, NamingStrategy namingStrat var schema = this.PayloadVisit(dataType: "array", dataFormat: null); // Gets the schema for the underlying type. - var underlyingType = type.GetElementType() ?? type.GetGenericArguments()[0]; + var underlyingType = type.GetUnderlyingType(); var items = this.VisitorCollection.PayloadVisit(underlyingType, namingStrategy); // Adds the reference to the schema for the underlying type. - var reference = new OpenApiReference() + if (underlyingType.IsReferentialType()) { - Type = ReferenceType.Schema, - Id = underlyingType.GetOpenApiReferenceId(isDictionary: false, isList: false, namingStrategy) - }; + var reference = new OpenApiReference() + { + Type = ReferenceType.Schema, + Id = underlyingType.GetOpenApiReferenceId(isDictionary: false, isList: false, namingStrategy) + }; - items.Reference = reference; + items.Reference = reference; + } schema.Items = items; diff --git a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/NullableObjectTypeVisitor.cs b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/NullableObjectTypeVisitor.cs index b4ece22..1a2bc85 100644 --- a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/NullableObjectTypeVisitor.cs +++ b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/NullableObjectTypeVisitor.cs @@ -88,7 +88,7 @@ public override bool IsParameterVisitable(Type type) /// public override OpenApiSchema ParameterVisit(Type type, NamingStrategy namingStrategy) { - type.IsOpenApiNullable(out var underlyingType); + var underlyingType = type.GetUnderlyingType(); var schema = this.VisitorCollection.ParameterVisit(underlyingType, namingStrategy); schema.Nullable = true; @@ -107,7 +107,7 @@ public override bool IsPayloadVisitable(Type type) /// public override OpenApiSchema PayloadVisit(Type type, NamingStrategy namingStrategy) { - type.IsOpenApiNullable(out var underlyingType); + var underlyingType = type.GetUnderlyingType(); var schema = this.VisitorCollection.PayloadVisit(underlyingType, namingStrategy); schema.Nullable = true; diff --git a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/TypeVisitor.cs b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/TypeVisitor.cs index c262b20..2a17260 100644 --- a/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/TypeVisitor.cs +++ b/src/Aliencube.AzureFunctions.Extensions.OpenApi.Core/Visitors/TypeVisitor.cs @@ -105,33 +105,7 @@ protected bool IsVisitable(Type type, TypeCode code) /// Returns True, if the type can be referenced; otherwise returns False. protected bool IsReferential(Type type) { - var @enum = Type.GetTypeCode(type); - var isReferential = @enum == TypeCode.Object; - - if (type == typeof(Guid)) - { - isReferential = false; - } - if (type == typeof(DateTime)) - { - isReferential = false; - } - if (type == typeof(DateTimeOffset)) - { - isReferential = false; - } - if (type.IsOpenApiNullable()) - { - isReferential = false; - } - if (type.IsUnflaggedEnumType()) - { - isReferential = false; - } - if (type.IsJObjectType()) - { - isReferential = false; - } + var isReferential = type.IsReferentialType(); return isReferential; } diff --git a/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Extensions/OpenApiPayloadAttributeExtensionsTests.cs b/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Extensions/OpenApiPayloadAttributeExtensionsTests.cs new file mode 100644 index 0000000..229d98d --- /dev/null +++ b/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Extensions/OpenApiPayloadAttributeExtensionsTests.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Net; + +using Aliencube.AzureFunctions.Extensions.OpenApi.Core.Attributes; +using Aliencube.AzureFunctions.Extensions.OpenApi.Core.Extensions; +using Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests.Fakes; + +using FluentAssertions; + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using Newtonsoft.Json.Serialization; + +namespace Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests.Extensions +{ + [TestClass] + public class OpenApiPayloadAttributeExtensionsTests + { + [TestMethod] + public void Given_Null_When_ToOpenApiMediaType_Invoked_Then_It_Should_Throw_Exception() + { + Action action = () => OpenApiPayloadAttributeExtensions.ToOpenApiMediaType((OpenApiPayloadAttribute)null); + + action.Should().Throw(); + } + + [DataTestMethod] + [DataRow(typeof(string), "string")] + [DataRow(typeof(FakeModel), "object")] + public void Given_OpenApiRequestBodyAttribute_When_ToOpenApiMediaType_Invoked_Then_It_Should_Return_Result(Type bodyType, string expected) + { + var contentType = "application/json"; + var attribute = new OpenApiRequestBodyAttribute(contentType, bodyType) + { + Required = true, + Description = "Dummy request model" + }; + var namingStrategy = new CamelCaseNamingStrategy(); + + var result = OpenApiPayloadAttributeExtensions.ToOpenApiMediaType(attribute, namingStrategy); + + result.Schema.Type.Should().Be(expected); + } + + [DataTestMethod] + [DataRow(typeof(string), "string", false, false, null)] + [DataRow(typeof(FakeModel), "object", false, false, null)] + [DataRow(typeof(List), "array", true, false, "string")] + [DataRow(typeof(Dictionary), "object", false, true, "integer")] + public void Given_OpenApiResponseWithBodyAttribute_When_ToOpenApiMediaType_Invoked_Then_It_Should_Return_Result(Type bodyType, string expected, bool items, bool additionalProperties, string underlyingType) + { + var statusCode = HttpStatusCode.OK; + var contentType = "application/json"; + var attribute = new OpenApiResponseWithBodyAttribute(statusCode, contentType, bodyType); + var namingStrategy = new CamelCaseNamingStrategy(); + + var result = OpenApiPayloadAttributeExtensions.ToOpenApiMediaType(attribute, namingStrategy); + + result.Schema.Type.Should().Be(expected); + if (items) + { + result.Schema.Items.Should().NotBeNull(); + result.Schema.Items.Type.Should().Be(underlyingType); + } + else + { + result.Schema.Items.Should().BeNull(); + } + + if (additionalProperties) + { + result.Schema.AdditionalProperties.Should().NotBeNull(); + result.Schema.AdditionalProperties.Type.Should().Be(underlyingType); + } + else + { + result.Schema.AdditionalProperties.Should().BeNull(); + } + } + } +} diff --git a/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Extensions/TypeExtensionsTests.cs b/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Extensions/TypeExtensionsTests.cs index 0607762..d8a20b3 100644 --- a/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Extensions/TypeExtensionsTests.cs +++ b/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Extensions/TypeExtensionsTests.cs @@ -125,5 +125,18 @@ public void Given_NullableDictionaryType_When_GetUnderlyingType_Invoked_Then_It_ result.Should().Be(expected); } + + [DataTestMethod] + [DataRow(typeof(int), false)] + [DataRow(typeof(int?), false)] + [DataRow(typeof(List), true)] + [DataRow(typeof(FakeModel), true)] + [DataRow(typeof(JObject), false)] + public void Given_Type_When_IsReferentialType_Invoked_Then_It_Should_Return_Result(Type type, bool expected) + { + var result = TypeExtensions.IsReferentialType(type); + + result.Should().Be(expected); + } } } diff --git a/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Visitors/DictionaryObjectTypeVisitorTests.cs b/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Visitors/DictionaryObjectTypeVisitorTests.cs index 5717679..6f6f1db 100644 --- a/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Visitors/DictionaryObjectTypeVisitorTests.cs +++ b/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Visitors/DictionaryObjectTypeVisitorTests.cs @@ -146,15 +146,15 @@ public void Given_Type_When_ParameterVisit_Invoked_Then_It_Should_Return_Result( } [DataTestMethod] - [DataRow(typeof(Dictionary), "object", null, "string", "string")] - [DataRow(typeof(IDictionary), "object", null, "string", "string")] - [DataRow(typeof(IReadOnlyDictionary), "object", null, "string", "string")] - [DataRow(typeof(KeyValuePair), "object", null, "string", "string")] - [DataRow(typeof(Dictionary), "object", null, "object", "fakeModel")] - [DataRow(typeof(IDictionary), "object", null, "object", "fakeModel")] - [DataRow(typeof(IReadOnlyDictionary), "object", null, "object", "fakeModel")] - [DataRow(typeof(KeyValuePair), "object", null, "object", "fakeModel")] - public void Given_Type_When_PayloadVisit_Invoked_Then_It_Should_Return_Result(Type dictionaryType, string dataType, string dataFormat, string additionalPropertyType, string referenceId) + [DataRow(typeof(Dictionary), "object", null, "string", false, null)] + [DataRow(typeof(IDictionary), "object", null, "string", false, null)] + [DataRow(typeof(IReadOnlyDictionary), "object", null, "string", false, null)] + [DataRow(typeof(KeyValuePair), "object", null, "string", false, null)] + [DataRow(typeof(Dictionary), "object", null, "object", true, "fakeModel")] + [DataRow(typeof(IDictionary), "object", null, "object", true, "fakeModel")] + [DataRow(typeof(IReadOnlyDictionary), "object", null, "object", true, "fakeModel")] + [DataRow(typeof(KeyValuePair), "object", null, "object", true, "fakeModel")] + public void Given_Type_When_PayloadVisit_Invoked_Then_It_Should_Return_Result(Type dictionaryType, string dataType, string dataFormat, string additionalPropertyType, bool reference, string referenceId) { var result = this._visitor.PayloadVisit(dictionaryType, this._strategy); @@ -164,8 +164,15 @@ public void Given_Type_When_PayloadVisit_Invoked_Then_It_Should_Return_Result(Ty result.AdditionalProperties.Should().NotBeNull(); result.AdditionalProperties.Type.Should().Be(additionalPropertyType); - result.AdditionalProperties.Reference.Type.Should().Be(ReferenceType.Schema); - result.AdditionalProperties.Reference.Id.Should().Be(referenceId); + if (reference) + { + result.AdditionalProperties.Reference.Type.Should().Be(ReferenceType.Schema); + result.AdditionalProperties.Reference.Id.Should().Be(referenceId); + } + else + { + result.AdditionalProperties.Reference.Should().BeNull(); + } } } } diff --git a/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Visitors/ListObjectTypeVisitorTests.cs b/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Visitors/ListObjectTypeVisitorTests.cs index 88a5eed..173b2ac 100644 --- a/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Visitors/ListObjectTypeVisitorTests.cs +++ b/test/Aliencube.AzureFunctions.Extensions.OpenApi.Core.Tests/Visitors/ListObjectTypeVisitorTests.cs @@ -171,19 +171,19 @@ public void Given_Type_When_ParameterVisit_Invoked_Then_It_Should_Return_Result( } [DataTestMethod] - [DataRow(typeof(List), "array", null, "string", "string")] - [DataRow(typeof(IList), "array", null, "string", "string")] - [DataRow(typeof(ICollection), "array", null, "string", "string")] - [DataRow(typeof(IEnumerable), "array", null, "string", "string")] - [DataRow(typeof(IReadOnlyList), "array", null, "string", "string")] - [DataRow(typeof(IReadOnlyCollection), "array", null, "string", "string")] - [DataRow(typeof(List), "array", null, "object", "fakeModel")] - [DataRow(typeof(IList), "array", null, "object", "fakeModel")] - [DataRow(typeof(ICollection), "array", null, "object", "fakeModel")] - [DataRow(typeof(IEnumerable), "array", null, "object", "fakeModel")] - [DataRow(typeof(IReadOnlyList), "array", null, "object", "fakeModel")] - [DataRow(typeof(IReadOnlyCollection), "array", null, "object", "fakeModel")] - public void Given_Type_When_PayloadVisit_Invoked_Then_It_Should_Return_Result(Type listType, string dataType, string dataFormat, string itemType, string referenceId) + [DataRow(typeof(List), "array", null, "string", false, null)] + [DataRow(typeof(IList), "array", null, "string", false, null)] + [DataRow(typeof(ICollection), "array", null, "string", false, null)] + [DataRow(typeof(IEnumerable), "array", null, "string", false, null)] + [DataRow(typeof(IReadOnlyList), "array", null, "string", false, null)] + [DataRow(typeof(IReadOnlyCollection), "array", null, "string", false, null)] + [DataRow(typeof(List), "array", null, "object", true, "fakeModel")] + [DataRow(typeof(IList), "array", null, "object", true, "fakeModel")] + [DataRow(typeof(ICollection), "array", null, "object", true, "fakeModel")] + [DataRow(typeof(IEnumerable), "array", null, "object", true, "fakeModel")] + [DataRow(typeof(IReadOnlyList), "array", null, "object", true, "fakeModel")] + [DataRow(typeof(IReadOnlyCollection), "array", null, "object", true, "fakeModel")] + public void Given_Type_When_PayloadVisit_Invoked_Then_It_Should_Return_Result(Type listType, string dataType, string dataFormat, string itemType, bool reference, string referenceId) { var result = this._visitor.PayloadVisit(listType, this._strategy); @@ -193,8 +193,15 @@ public void Given_Type_When_PayloadVisit_Invoked_Then_It_Should_Return_Result(Ty result.Items.Should().NotBeNull(); result.Items.Type.Should().Be(itemType); - result.Items.Reference.Type.Should().Be(ReferenceType.Schema); - result.Items.Reference.Id.Should().Be(referenceId); + if (reference) + { + result.Items.Reference.Type.Should().Be(ReferenceType.Schema); + result.Items.Reference.Id.Should().Be(referenceId); + } + else + { + result.Items.Reference.Should().BeNull(); + } } } }