Skip to content

Commit 99dcfa8

Browse files
committed
Added tests for nullable and required properties in schema generation
1 parent a3fd9bc commit 99dcfa8

13 files changed

+445
-0
lines changed

test/OpenApiTests/JsonElementExtensions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ public static JsonElement ShouldContainPath(this JsonElement source, string path
1919
return elementSelector.Should().NotThrow().Subject;
2020
}
2121

22+
public static void ShouldNotContainPath(this JsonElement source, string path)
23+
{
24+
JsonElement? pathToken = source.SelectToken(path);
25+
26+
pathToken.Should().BeNull();
27+
}
28+
2229
public static void ShouldBeString(this JsonElement source, string value)
2330
{
2431
source.ValueKind.Should().Be(JsonValueKind.String);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Text.Json.Serialization;
2+
using JetBrains.Annotations;
3+
using JsonApiDotNetCore.Configuration;
4+
using Microsoft.EntityFrameworkCore;
5+
6+
namespace OpenApiTests.SchemaProperties;
7+
8+
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
9+
public sealed class ModelStateValidationDisabledStartup<TDbContext> : OpenApiStartup<TDbContext>
10+
where TDbContext : DbContext
11+
{
12+
protected override void SetJsonApiOptions(JsonApiOptions options)
13+
{
14+
base.SetJsonApiOptions(options);
15+
16+
options.SerializerOptions.Converters.Add(new JsonStringEnumConverter());
17+
options.ValidateModelState = false;
18+
}
19+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#nullable disable
2+
3+
using System.ComponentModel.DataAnnotations;
4+
using JetBrains.Annotations;
5+
using JsonApiDotNetCore.Resources;
6+
using JsonApiDotNetCore.Resources.Annotations;
7+
8+
namespace OpenApiTests.SchemaProperties.NullableReferenceTypesDisabled;
9+
10+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
11+
[Resource(ControllerNamespace = "OpenApiTests.SchemaProperties")]
12+
public sealed class Chicken : Identifiable<int>
13+
{
14+
[Attr]
15+
public string Name { get; set; }
16+
17+
[Attr]
18+
[Required]
19+
public string NameOfCurrentFarm { get; set; }
20+
21+
[Attr]
22+
public int Age { get; set; }
23+
24+
[Attr]
25+
[Required]
26+
public int Weight { get; set; }
27+
28+
[Attr]
29+
public int? TimeAtCurrentFarmInDays { get; set; }
30+
31+
[Attr]
32+
[Required]
33+
public bool? HasProducedEggs { get; set; }
34+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Text.Json;
2+
using FluentAssertions;
3+
using TestBuildingBlocks;
4+
using Xunit;
5+
6+
namespace OpenApiTests.SchemaProperties.NullableReferenceTypesDisabled;
7+
8+
public sealed class ModelStateValidationDisabledTests
9+
: IClassFixture<OpenApiTestContext<ModelStateValidationDisabledStartup<NullableReferenceTypesDisabledDbContext>, NullableReferenceTypesDisabledDbContext>>
10+
{
11+
private readonly OpenApiTestContext<ModelStateValidationDisabledStartup<NullableReferenceTypesDisabledDbContext>, NullableReferenceTypesDisabledDbContext>
12+
_testContext;
13+
14+
public ModelStateValidationDisabledTests(
15+
OpenApiTestContext<ModelStateValidationDisabledStartup<NullableReferenceTypesDisabledDbContext>, NullableReferenceTypesDisabledDbContext> testContext)
16+
{
17+
_testContext = testContext;
18+
testContext.UseController<ChickensController>();
19+
}
20+
21+
[Fact]
22+
public async Task Resource_when_ModelStateValidation_is_disabled_produces_expected_required_property_in_schema()
23+
{
24+
// Act
25+
JsonElement document = await _testContext.GetSwaggerDocumentAsync();
26+
27+
// Assert
28+
document.ShouldContainPath("components.schemas.chickenAttributesInPostRequest.required").With(requiredElement =>
29+
{
30+
var requiredAttributes = JsonSerializer.Deserialize<List<string>>(requiredElement.GetRawText());
31+
requiredAttributes.ShouldNotBeNull();
32+
33+
requiredAttributes.Should().Contain("nameOfCurrentFarm");
34+
requiredAttributes.Should().Contain("weight");
35+
requiredAttributes.Should().Contain("hasProducedEggs");
36+
37+
requiredAttributes.ShouldHaveCount(3);
38+
});
39+
}
40+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Text.Json;
2+
using FluentAssertions;
3+
using TestBuildingBlocks;
4+
using Xunit;
5+
6+
namespace OpenApiTests.SchemaProperties.NullableReferenceTypesDisabled;
7+
8+
public sealed class ModelStateValidationEnabledTests
9+
: IClassFixture<OpenApiTestContext<SchemaPropertiesStartup<NullableReferenceTypesDisabledDbContext>, NullableReferenceTypesDisabledDbContext>>
10+
{
11+
private readonly OpenApiTestContext<SchemaPropertiesStartup<NullableReferenceTypesDisabledDbContext>, NullableReferenceTypesDisabledDbContext> _testContext;
12+
13+
public ModelStateValidationEnabledTests(
14+
OpenApiTestContext<SchemaPropertiesStartup<NullableReferenceTypesDisabledDbContext>, NullableReferenceTypesDisabledDbContext> testContext)
15+
{
16+
_testContext = testContext;
17+
18+
testContext.UseController<ChickensController>();
19+
}
20+
21+
[Fact]
22+
public async Task Resource_when_ModelStateValidation_is_enabled_produces_expected_required_property_in_schema()
23+
{
24+
// Act
25+
JsonElement document = await _testContext.GetSwaggerDocumentAsync();
26+
27+
// Assert
28+
document.ShouldContainPath("components.schemas.chickenAttributesInPostRequest.required").With(requiredElement =>
29+
{
30+
var requiredAttributes = JsonSerializer.Deserialize<List<string>>(requiredElement.GetRawText());
31+
requiredAttributes.ShouldNotBeNull();
32+
33+
requiredAttributes.Should().Contain("nameOfCurrentFarm");
34+
requiredAttributes.Should().Contain("weight");
35+
requiredAttributes.Should().Contain("hasProducedEggs");
36+
37+
requiredAttributes.ShouldHaveCount(3);
38+
});
39+
}
40+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System.Text.Json;
2+
using FluentAssertions;
3+
using TestBuildingBlocks;
4+
using Xunit;
5+
6+
namespace OpenApiTests.SchemaProperties.NullableReferenceTypesDisabled;
7+
8+
public sealed class NullabilityTests
9+
: IClassFixture<OpenApiTestContext<SchemaPropertiesStartup<NullableReferenceTypesDisabledDbContext>, NullableReferenceTypesDisabledDbContext>>
10+
{
11+
private readonly OpenApiTestContext<SchemaPropertiesStartup<NullableReferenceTypesDisabledDbContext>, NullableReferenceTypesDisabledDbContext> _testContext;
12+
13+
public NullabilityTests(
14+
OpenApiTestContext<SchemaPropertiesStartup<NullableReferenceTypesDisabledDbContext>, NullableReferenceTypesDisabledDbContext> testContext)
15+
{
16+
_testContext = testContext;
17+
18+
testContext.UseController<ChickensController>();
19+
testContext.SwaggerDocumentOutputPath = "test/OpenApiClientTests/SchemaProperties/NullableReferenceTypesDisabled";
20+
}
21+
22+
[Fact]
23+
public async Task Resource_produces_expected_nullable_properties_in_schema()
24+
{
25+
// Act
26+
JsonElement document = await _testContext.GetSwaggerDocumentAsync();
27+
28+
// Assert
29+
document.ShouldContainPath("components.schemas.chickenAttributesInResponse.properties").With(propertiesElement =>
30+
{
31+
propertiesElement.ShouldContainPath("name").With(propertyElement =>
32+
{
33+
propertyElement.ShouldContainPath("nullable").With(nullableProperty => nullableProperty.ValueKind.Should().Be(JsonValueKind.True));
34+
});
35+
36+
propertiesElement.ShouldContainPath("nameOfCurrentFarm").With(propertyElement =>
37+
{
38+
propertyElement.ShouldNotContainPath("nullable");
39+
});
40+
41+
propertiesElement.ShouldContainPath("age").With(propertyElement =>
42+
{
43+
propertyElement.ShouldNotContainPath("nullable");
44+
});
45+
46+
propertiesElement.ShouldContainPath("weight").With(propertyElement =>
47+
{
48+
propertyElement.ShouldNotContainPath("nullable");
49+
});
50+
51+
propertiesElement.ShouldContainPath("timeAtCurrentFarmInDays").With(propertyElement =>
52+
{
53+
propertyElement.ShouldContainPath("nullable").With(nullableProperty => nullableProperty.ValueKind.Should().Be(JsonValueKind.True));
54+
});
55+
56+
propertiesElement.ShouldContainPath("hasProducedEggs").With(propertyElement =>
57+
{
58+
propertyElement.ShouldNotContainPath("nullable");
59+
});
60+
});
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using JetBrains.Annotations;
2+
using Microsoft.EntityFrameworkCore;
3+
4+
namespace OpenApiTests.SchemaProperties.NullableReferenceTypesDisabled;
5+
6+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
7+
public sealed class NullableReferenceTypesDisabledDbContext : DbContext
8+
{
9+
public DbSet<Chicken> Chicken => Set<Chicken>();
10+
11+
public NullableReferenceTypesDisabledDbContext(DbContextOptions<NullableReferenceTypesDisabledDbContext> options)
12+
: base(options)
13+
{
14+
}
15+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System.ComponentModel.DataAnnotations;
2+
using JetBrains.Annotations;
3+
using JsonApiDotNetCore.Resources;
4+
using JsonApiDotNetCore.Resources.Annotations;
5+
6+
namespace OpenApiTests.SchemaProperties.NullableReferenceTypesEnabled;
7+
8+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
9+
[Resource(ControllerNamespace = "OpenApiTests.SchemaProperties")]
10+
public sealed class Cow : Identifiable<int>
11+
{
12+
[Attr]
13+
public string Name { get; set; } = null!;
14+
15+
[Attr]
16+
[Required]
17+
public string NameOfCurrentFarm { get; set; } = null!;
18+
19+
[Attr]
20+
public string? NameOfPreviousFarm { get; set; }
21+
22+
[Attr]
23+
[Required]
24+
public string? Nickname { get; set; }
25+
26+
[Attr]
27+
public int Age { get; set; }
28+
29+
[Attr]
30+
[Required]
31+
public int Weight { get; set; }
32+
33+
[Attr]
34+
public int? TimeAtCurrentFarmInDays { get; set; }
35+
36+
[Attr]
37+
[Required]
38+
public bool? HasProducedMilk { get; set; }
39+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System.Text.Json;
2+
using FluentAssertions;
3+
using TestBuildingBlocks;
4+
using Xunit;
5+
6+
namespace OpenApiTests.SchemaProperties.NullableReferenceTypesEnabled;
7+
8+
public sealed class ModelStateValidationDisabledTests
9+
: IClassFixture<OpenApiTestContext<ModelStateValidationDisabledStartup<NullableReferenceTypesEnabledDbContext>, NullableReferenceTypesEnabledDbContext>>
10+
{
11+
private readonly OpenApiTestContext<ModelStateValidationDisabledStartup<NullableReferenceTypesEnabledDbContext>, NullableReferenceTypesEnabledDbContext>
12+
_testContext;
13+
14+
public ModelStateValidationDisabledTests(
15+
OpenApiTestContext<ModelStateValidationDisabledStartup<NullableReferenceTypesEnabledDbContext>, NullableReferenceTypesEnabledDbContext> testContext)
16+
{
17+
_testContext = testContext;
18+
19+
testContext.UseController<CowsController>();
20+
}
21+
22+
[Fact]
23+
public async Task Resource_when_ModelStateValidation_is_disabled_produces_expected_required_property_in_schema()
24+
{
25+
// Act
26+
JsonElement document = await _testContext.GetSwaggerDocumentAsync();
27+
28+
// Assert
29+
document.ShouldContainPath("components.schemas.cowAttributesInPostRequest.required").With(requiredElement =>
30+
{
31+
var requiredAttributes = JsonSerializer.Deserialize<List<string>>(requiredElement.GetRawText());
32+
requiredAttributes.ShouldNotBeNull();
33+
34+
requiredAttributes.Should().Contain("nameOfCurrentFarm");
35+
requiredAttributes.Should().Contain("nickname");
36+
requiredAttributes.Should().Contain("weight");
37+
requiredAttributes.Should().Contain("hasProducedMilk");
38+
39+
requiredAttributes.ShouldHaveCount(4);
40+
});
41+
}
42+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System.Text.Json;
2+
using FluentAssertions;
3+
using TestBuildingBlocks;
4+
using Xunit;
5+
6+
namespace OpenApiTests.SchemaProperties.NullableReferenceTypesEnabled;
7+
8+
public sealed class ModelStateValidationEnabledTests
9+
: IClassFixture<OpenApiTestContext<SchemaPropertiesStartup<NullableReferenceTypesEnabledDbContext>, NullableReferenceTypesEnabledDbContext>>
10+
{
11+
private readonly OpenApiTestContext<SchemaPropertiesStartup<NullableReferenceTypesEnabledDbContext>, NullableReferenceTypesEnabledDbContext> _testContext;
12+
13+
public ModelStateValidationEnabledTests(
14+
OpenApiTestContext<SchemaPropertiesStartup<NullableReferenceTypesEnabledDbContext>, NullableReferenceTypesEnabledDbContext> testContext)
15+
{
16+
_testContext = testContext;
17+
18+
testContext.UseController<CowsController>();
19+
}
20+
21+
[Fact]
22+
public async Task Resource_when_ModelStateValidation_is_enabled_produces_expected_required_property_in_schema()
23+
{
24+
// Act
25+
JsonElement document = await _testContext.GetSwaggerDocumentAsync();
26+
27+
// Assert
28+
document.ShouldContainPath("components.schemas.cowAttributesInPostRequest.required").With(requiredElement =>
29+
{
30+
var requiredAttributes = JsonSerializer.Deserialize<List<string>>(requiredElement.GetRawText());
31+
requiredAttributes.ShouldNotBeNull();
32+
33+
requiredAttributes.Should().Contain("name");
34+
requiredAttributes.Should().Contain("nameOfCurrentFarm");
35+
requiredAttributes.Should().Contain("nickname");
36+
requiredAttributes.Should().Contain("weight");
37+
requiredAttributes.Should().Contain("hasProducedMilk");
38+
39+
requiredAttributes.ShouldHaveCount(5);
40+
});
41+
}
42+
}

0 commit comments

Comments
 (0)