Improve BeEquivalentTo error messages by ronaldkroon · Pull Request #34 · fluentassertions/fluentassertions.json · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions FluentAssertions.Json.sln.DotSettings
4 changes: 2 additions & 2 deletions Src/FluentAssertions.Json/JTokenAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ public AndConstraint<JTokenAssertions> BeEquivalentTo(JToken expected, string be
Difference difference = JTokenDifferentiator.FindFirstDifference(Subject, expected);

var message = $"JSON document {difference?.ToString().Escape(true)}.{Environment.NewLine}" +
$"Expected{Environment.NewLine}" +
$"Actual document{Environment.NewLine}" +
$"{Format(Subject, true).Escape(true)}{Environment.NewLine}" +
$"to be equivalent to{Environment.NewLine}" +
$"was expected to be equivalent to{Environment.NewLine}" +
$"{Format(expected, true).Escape(true)}{Environment.NewLine}" +
"{reason}.";

Expand Down
70 changes: 61 additions & 9 deletions Src/FluentAssertions.Json/JTokenDifferentiator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private static Difference FindJArrayDifference(JArray actualArray, JToken expect
{
if (!(expected is JArray expectedArray))
{
return new Difference(DifferenceKind.OtherType, path);
return new Difference(DifferenceKind.OtherType, path, Describe(actualArray.Type), Describe(expected.Type));
}

return CompareItems(actualArray, expectedArray, path);
Expand All @@ -63,7 +63,7 @@ private static Difference CompareItems(JArray actual, JArray expected, JPath pat

if (actualChildren.Count() != expectedChildren.Count())
{
return new Difference(DifferenceKind.DifferentLength, path);
return new Difference(DifferenceKind.DifferentLength, path, actualChildren.Count(), expectedChildren.Count());
}

for (int i = 0; i < actualChildren.Count(); i++)
Expand All @@ -84,7 +84,7 @@ private static Difference FindJObjectDifference(JObject actual, JToken expected,
{
if (!(expected is JObject expectedObject))
{
return new Difference(DifferenceKind.OtherType, path);
return new Difference(DifferenceKind.OtherType, path, Describe(actual.Type), Describe(expected.Type));
}

return CompareProperties(actual?.Properties(), expectedObject.Properties(), path);
Expand Down Expand Up @@ -131,7 +131,7 @@ private static Difference FindJPropertyDifference(JProperty actualProperty, JTok
{
if (!(expected is JProperty expectedProperty))
{
return new Difference(DifferenceKind.OtherType, path);
return new Difference(DifferenceKind.OtherType, path, Describe(actualProperty.Type), Describe(expected.Type));
}

if (actualProperty.Name != expectedProperty.Name)
Expand All @@ -146,7 +146,7 @@ private static Difference FindValueDifference(JValue actualValue, JToken expecte
{
if (!(expected is JValue expectedValue))
{
return new Difference(DifferenceKind.OtherType, path);
return new Difference(DifferenceKind.OtherType, path, Describe(actualValue.Type), Describe(expected.Type));
}

return CompareValues(actualValue, expectedValue, path);
Expand All @@ -156,7 +156,7 @@ private static Difference CompareValues(JValue actual, JValue expected, JPath pa
{
if (actual.Type != expected.Type)
{
return new Difference(DifferenceKind.OtherType, path);
return new Difference(DifferenceKind.OtherType, path, Describe(actual.Type), Describe(expected.Type));
}

if (!actual.Equals(expected))
Expand All @@ -166,19 +166,71 @@ private static Difference CompareValues(JValue actual, JValue expected, JPath pa

return null;
}

private static string Describe(JTokenType jTokenType)
{
switch (jTokenType)
{
case JTokenType.None:
return "type none";
case JTokenType.Object:
return "an object";
case JTokenType.Array:
return "an array";
case JTokenType.Constructor:
return "a constructor";
case JTokenType.Property:
return "a property";
case JTokenType.Comment:
return "a comment";
case JTokenType.Integer:
return "an integer";
case JTokenType.Float:
return "a float";
case JTokenType.String:
return "a string";
case JTokenType.Boolean:
return "a boolean";
case JTokenType.Null:
return "type null";
case JTokenType.Undefined:
return "type undefined";
case JTokenType.Date:
return "a date";
case JTokenType.Raw:
return "type raw";
case JTokenType.Bytes:
return "type bytes";
case JTokenType.Guid:
return "a GUID";
case JTokenType.Uri:
return "a URI";
case JTokenType.TimeSpan:
return "a timespan";
default:
throw new ArgumentOutOfRangeException(nameof(jTokenType), jTokenType, null);
}
}
}

internal class Difference
{
public Difference(DifferenceKind kind, JPath path, object actual, object expected) : this(kind, path)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't actual and expected be of type string?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also passing ints. This way I don't have to call ToString.

{
Actual = actual;
Expected = expected;
}

public Difference(DifferenceKind kind, JPath path)
{
Kind = kind;
Path = path;
}

private DifferenceKind Kind { get; }

private JPath Path { get; }
private object Actual { get; }
private object Expected { get; }

public override string ToString()
{
Expand All @@ -189,13 +241,13 @@ public override string ToString()
case DifferenceKind.ExpectedIsNull:
return "is not null";
case DifferenceKind.OtherType:
return $"has a different type at {Path}";
return $"has {Actual} instead of {Expected} at {Path}";
case DifferenceKind.OtherName:
return $"has a different name at {Path}";
case DifferenceKind.OtherValue:
return $"has a different value at {Path}";
case DifferenceKind.DifferentLength:
return $"has a different length at {Path}";
return $"has {Actual} elements instead of {Expected} at {Path}";
case DifferenceKind.ActualMissesProperty:
return $"misses property {Path}";
case DifferenceKind.ExpectedMissesProperty:
Expand Down
161 changes: 86 additions & 75 deletions Tests/FluentAssertions.Json.Shared.Specs/JTokenAssertionsSpecs.cs