Skip to content

Commit

Permalink
Add new overrides BeJsonDeserializableInto() to test the string colle…
Browse files Browse the repository at this point in the history
…ctions, string and numeric values (#16).
  • Loading branch information
GillesTourreau committed Jun 18, 2024
1 parent 167e385 commit 389e434
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/FluentAssertions.Json/FluentAssertions.Json.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
<PackageProjectUrl>https://github.com/PosInformatique/PosInformatique.FluentAssertions.Json</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageReleaseNotes>
1.3.0
- Add new override BeJsonDeserializableInto() method to test the string collections.
- Add new override BeJsonDeserializableInto() method to test the string and numeric values.

1.2.0
- Add new override BeJsonSerializableInto() method to test polymorphism serialization with discriminator JSON property.
- Add the support to assert the deserialization of root JSON array.
Expand Down
98 changes: 97 additions & 1 deletion src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace FluentAssertions
using FluentAssertions.Collections;
using FluentAssertions.Common;
using FluentAssertions.Equivalency;
using FluentAssertions.Numeric;
using FluentAssertions.Primitives;
using PosInformatique.FluentAssertions.Json;

Expand Down Expand Up @@ -105,7 +106,7 @@ public static void BeJsonDeserializableInto<T>(this ObjectAssertions assertions,
/// </summary>
/// <typeparam name="TElement">Type of the element of the collection to check the JSON deserialization.</typeparam>
/// <typeparam name="T">Type of the object to deserialize from JSON.</typeparam>
/// <param name="assertions"><see cref="ObjectAssertions"/> which contains the JSON collection subject to deserialize.</param>
/// <param name="assertions"><see cref="GenericCollectionAssertions{T}"/> which contains the JSON collection subject to deserialize.</param>
/// <param name="expectedObject">Expected collection deserialized expected.</param>
/// <param name="options"><see cref="JsonSerializerOptions"/> to use to assert the deserialization. If not specified
/// the default <see cref="IFluentAssertionsJsonConfiguration.JsonSerializerOptions"/> of the <see cref="FluentAssertionsJson.Configuration"/>
Expand All @@ -115,6 +116,49 @@ public static void BeJsonDeserializableInto<TElement, T>(this GenericCollectionA
BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, GetSerializerOptions(options));
}

/// <summary>
/// Check if the JSON subject string collection is deserializable into the specified <paramref name="expectedObject"/> argument.
/// </summary>
/// <typeparam name="T">Type of the object to deserialize from JSON.</typeparam>
/// <param name="assertions"><see cref="StringCollectionAssertions"/> which contains the JSON string collection subject to deserialize.</param>
/// <param name="expectedObject">Expected string collection deserialized expected.</param>
/// <param name="options"><see cref="JsonSerializerOptions"/> to use to assert the deserialization. If not specified
/// the default <see cref="IFluentAssertionsJsonConfiguration.JsonSerializerOptions"/> of the <see cref="FluentAssertionsJson.Configuration"/>
/// will be used.</param>
public static void BeJsonDeserializableInto<T>(this StringCollectionAssertions assertions, T expectedObject, JsonSerializerOptions? options = null)
{
BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, GetSerializerOptions(options));
}

/// <summary>
/// Check if the JSON subject numeric is deserializable into the specified <paramref name="expectedObject"/> argument.
/// </summary>
/// <typeparam name="T">Type of the object to deserialize from JSON.</typeparam>
/// <param name="assertions"><see cref="NumericAssertions{T}"/> which contains the JSON numeric subject to deserialize.</param>
/// <param name="expectedObject">Expected numeric value deserialized expected.</param>
/// <param name="options"><see cref="JsonSerializerOptions"/> to use to assert the deserialization. If not specified
/// the default <see cref="IFluentAssertionsJsonConfiguration.JsonSerializerOptions"/> of the <see cref="FluentAssertionsJson.Configuration"/>
/// will be used.</param>
public static void BeJsonDeserializableInto<T>(this NumericAssertions<T> assertions, T expectedObject, JsonSerializerOptions? options = null)
where T : struct, IComparable<T>
{
BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, GetSerializerOptions(options));

Check warning on line 145 in src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'subject' in 'void JsonFluentAssertionsExtensions.BeJsonDeserializableIntoCore<T>(object subject, T expectedObject, JsonSerializerOptions options)'.

Check warning on line 145 in src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'subject' in 'void JsonFluentAssertionsExtensions.BeJsonDeserializableIntoCore<T>(object subject, T expectedObject, JsonSerializerOptions options)'.

Check warning on line 145 in src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'subject' in 'void JsonFluentAssertionsExtensions.BeJsonDeserializableIntoCore<T>(object subject, T expectedObject, JsonSerializerOptions options)'.
}

/// <summary>
/// Check if the JSON subject string is deserializable into the specified <paramref name="expectedObject"/> argument.
/// </summary>
/// <typeparam name="T">Type of the object to deserialize from JSON.</typeparam>
/// <param name="assertions"><see cref="StringAssertions"/> which contains the JSON string subject to deserialize.</param>
/// <param name="expectedObject">Expected string value deserialized expected.</param>
/// <param name="options"><see cref="JsonSerializerOptions"/> to use to assert the deserialization. If not specified
/// the default <see cref="IFluentAssertionsJsonConfiguration.JsonSerializerOptions"/> of the <see cref="FluentAssertionsJson.Configuration"/>
/// will be used.</param>
public static void BeJsonDeserializableInto<T>(this StringAssertions assertions, T expectedObject, JsonSerializerOptions? options = null)
{
BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, GetSerializerOptions(options));
}

/// <summary>
/// Check if the JSON subject object is deserializable into the specified <paramref name="expectedObject"/> argument.
/// </summary>
Expand Down Expand Up @@ -150,6 +194,58 @@ public static void BeJsonDeserializableInto<TElement, T>(this GenericCollectionA
BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, optionsCopy);
}

/// <summary>
/// Check if the JSON subject string collection is deserializable into the specified <paramref name="expectedObject"/> argument.
/// </summary>
/// <typeparam name="T">Type of the object to deserialize from JSON.</typeparam>
/// <param name="assertions"><see cref="ObjectAssertions"/> which contains the JSON string collection subject to deserialize.</param>
/// <param name="expectedObject">Expected string collection deserialized expected.</param>
/// <param name="configureOptions">Allows to change the default <see cref="IFluentAssertionsJsonConfiguration.JsonSerializerOptions"/>
/// of the <see cref="FluentAssertionsJson.Configuration"/> used to assert the deserialization.</param>
public static void BeJsonDeserializableInto<T>(this StringCollectionAssertions assertions, T expectedObject, Action<JsonSerializerOptions> configureOptions)
{
var optionsCopy = new JsonSerializerOptions(FluentAssertionsJson.Configuration.JsonSerializerOptions);

configureOptions(optionsCopy);

BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, optionsCopy);
}

/// <summary>
/// Check if the JSON subject numeric is deserializable into the specified <paramref name="expectedObject"/> argument.
/// </summary>
/// <typeparam name="T">Type of the numeric value to deserialize from JSON.</typeparam>
/// <param name="assertions"><see cref="ObjectAssertions"/> which contains the JSON numeric subject to deserialize.</param>
/// <param name="expectedObject">Expected numeric value deserialized expected.</param>
/// <param name="configureOptions">Allows to change the default <see cref="IFluentAssertionsJsonConfiguration.JsonSerializerOptions"/>
/// of the <see cref="FluentAssertionsJson.Configuration"/> used to assert the deserialization.</param>
public static void BeJsonDeserializableInto<T>(this NumericAssertions<T> assertions, T expectedObject, Action<JsonSerializerOptions> configureOptions)
where T : struct, IComparable<T>
{
var optionsCopy = new JsonSerializerOptions(FluentAssertionsJson.Configuration.JsonSerializerOptions);

configureOptions(optionsCopy);

BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, optionsCopy);

Check warning on line 229 in src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'subject' in 'void JsonFluentAssertionsExtensions.BeJsonDeserializableIntoCore<T>(object subject, T expectedObject, JsonSerializerOptions options)'.

Check warning on line 229 in src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'subject' in 'void JsonFluentAssertionsExtensions.BeJsonDeserializableIntoCore<T>(object subject, T expectedObject, JsonSerializerOptions options)'.

Check warning on line 229 in src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'subject' in 'void JsonFluentAssertionsExtensions.BeJsonDeserializableIntoCore<T>(object subject, T expectedObject, JsonSerializerOptions options)'.
}

/// <summary>
/// Check if the JSON subject string is deserializable into the specified <paramref name="expectedObject"/> argument.
/// </summary>
/// <typeparam name="T">Type of the string value to deserialize from JSON.</typeparam>
/// <param name="assertions"><see cref="StringAssertions"/> which contains the JSON string subject to deserialize.</param>
/// <param name="expectedObject">Expected string value deserialized expected.</param>
/// <param name="configureOptions">Allows to change the default <see cref="IFluentAssertionsJsonConfiguration.JsonSerializerOptions"/>
/// of the <see cref="FluentAssertionsJson.Configuration"/> used to assert the deserialization.</param>
public static void BeJsonDeserializableInto<T>(this StringAssertions assertions, T expectedObject, Action<JsonSerializerOptions> configureOptions)
{
var optionsCopy = new JsonSerializerOptions(FluentAssertionsJson.Configuration.JsonSerializerOptions);

configureOptions(optionsCopy);

BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, optionsCopy);
}

private static void BeJsonSerializableIntoCore<TBase>(ObjectAssertions assertions, object? expectedJson, JsonSerializerOptions options)
{
if (assertions.Subject is not null && assertions.Subject is not TBase)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,103 @@ public void BeJsonDeserializableInto_WithObjectProperty_String_WrongType()
.WithMessage("$.inner.object_property: Expected property to be 'Number' type instead of 'String' type.");
}

[Fact]
public void BeJsonDeserializableInto_WithArrayOfString()
{
var json = new[] { "A", "B", "C" };

json.Should().BeJsonDeserializableInto(new[] { "A", "B", "C" });
}

[Fact]
public void BeJsonDeserializableInto_WithArrayOfString_WithOptions()
{
var json = new[] { "A", "B", "C" };

json.Should().BeJsonDeserializableInto(
new[] { "A", "B", "C" },
new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});
}

[Fact]
public void BeJsonDeserializableInto_ArrayOfString_WithOptionsConfigure()
{
var json = new[] { "A", "B", "C" };

json.Should().BeJsonDeserializableInto(
new[] { "A", "B", "C" },
opt =>
{
opt.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
}

[Fact]
public void BeJsonDeserializableInto_PrimitiveValues()
{
var json = "A";

json.Should().BeJsonDeserializableInto("A");

var json2 = 1234;

json2.Should().BeJsonDeserializableInto(1234);

var json3 = 12.34;

json3.Should().BeJsonDeserializableInto(12.34);
}

[Fact]
public void BeJsonDeserializableInto_PrimitiveValues_WithOptions()
{
var json = "A";

json.Should().BeJsonDeserializableInto("A", new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });

var json2 = 1234;

json2.Should().BeJsonDeserializableInto(1234, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });

var json3 = 12.34;

json3.Should().BeJsonDeserializableInto(12.34, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
}

[Fact]
public void BeJsonDeserializableInto_PrimitiveValues_WithOptionsConfigure()
{
var json = "A";

json.Should().BeJsonDeserializableInto(
"A",
opt =>
{
opt.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});

var json2 = 1234;

json2.Should().BeJsonDeserializableInto(
1234,
opt =>
{
opt.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});

var json3 = 12.34;

json3.Should().BeJsonDeserializableInto(
12.34,
opt =>
{
opt.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
}

private class JsonSerializableClass
{
[JsonPropertyName("string_property")]
Expand Down

0 comments on commit 389e434

Please sign in to comment.