Skip to content

Commit 3b946f1

Browse files
committed
JObject compatibility
1 parent a4c432c commit 3b946f1

6 files changed

Lines changed: 57 additions & 5 deletions

File tree

exampleTest/CheckTestOutput.Example.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
<ItemGroup>
1111
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
12+
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
1213
<PackageReference Include="xunit" Version="2.4.0" />
1314
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
1415
</ItemGroup>

exampleTest/SomeTest.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Text.RegularExpressions;
5+
using Newtonsoft.Json.Linq;
56
using Xunit;
67

78
namespace CheckTestOutput.Example
@@ -93,6 +94,15 @@ public void JsonWithNormalizedOrder()
9394
check.CheckJsonObject(dict, normalizePropertyOrder: true);
9495
}
9596

97+
[Fact]
98+
public void NewtonsoftJsonCompatibility()
99+
{
100+
check.CheckJsonObject(
101+
JObject.FromObject(new { number = 3, str = "jaja", list = new List<object> { 1, "2313", new SomeTestObject { Prop = "hmm" } } })
102+
);
103+
104+
}
105+
96106
class SomeTestObject
97107
{
98108
public string Prop { get; set; }
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"number": 3,
3+
"str": "jaja",
4+
"list": [
5+
1,
6+
"2313",
7+
{
8+
"Prop": "hmm"
9+
}
10+
]
11+
}

src/BasicChecks.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ namespace CheckTestOutput
77
{
88
public static class BasicChecks
99
{
10+
/// <summary> Verifies that the provided <paramref name="output" /> equals to the `outputDirectory/TestClass.TestMethod.txt` file. </summary>
11+
/// <param name="checkName"> If not null, checkName will be appended to the calling <paramref name="memberName" />. Intended to be used when having multiple checks in one method. </param>
1012
public static void CheckString(
1113
this OutputChecker t,
1214
string output,
@@ -23,6 +25,8 @@ public static void CheckString(
2325
);
2426
}
2527

28+
/// <summary> Verifies that the provided <paramref name="output" /> equals to the `outputDirectory/TestClass.TestMethod.txt` file. File is compared line-by-line. </summary>
29+
/// <param name="checkName"> If not null, checkName will be appended to the calling <paramref name="memberName" />. Intended to be used when having multiple checks in one method. </param>
2630
public static void CheckLines(
2731
this OutputChecker t,
2832
IEnumerable<string> output,

src/JsonChecks.cs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ namespace CheckTestOutput
99
{
1010
public static class JsonChecks
1111
{
12+
/// <summary> Verifies that the provided object <paramref name="output" />, serialized as Json using System.Text.Json, is equal to the `outputDirectory/TestClass.TestMethod.json` file. </summary>
13+
/// <param name="jsonOptions"> Json serialization options will be passed to <see cref="JsonSerializer.Serialize{TValue}(TValue, JsonSerializerOptions?)" />. </param>
14+
/// <param name="normalizePropertyOrder"> If true, object properties will be sorted alphabetically. </param>
15+
/// <param name="checkName"> If not null, checkName will be appended to the calling <paramref name="memberName" />. Intended to be used when having multiple checks in one method. </param>
1216
public static void CheckJsonObject(
1317
this OutputChecker t,
1418
object output,
@@ -20,8 +24,7 @@ public static void CheckJsonObject(
2024
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = null)
2125
{
2226
jsonOptions ??= new JsonSerializerOptions() { WriteIndented = true };
23-
var strOutput =
24-
JsonSerializer.Serialize(output, jsonOptions);
27+
var strOutput = SerializeJson(output, jsonOptions);
2528

2629
if (normalizePropertyOrder)
2730
{
@@ -34,7 +37,6 @@ public static void CheckJsonObject(
3437
strOutput = System.Text.Encoding.UTF8.GetString(outputStream.ToArray());
3538
}
3639

37-
3840
// indent using tabs for back compatibility
3941
strOutput = Regex.Replace(strOutput, "^( )+", m => new string('\t', m.Value.Length / 2), RegexOptions.Multiline);
4042
t.CheckOutputCore(
@@ -45,6 +47,28 @@ public static void CheckJsonObject(
4547
);
4648
}
4749

50+
static string SerializeJson(object obj, JsonSerializerOptions options)
51+
{
52+
if (obj is null) return "null";
53+
54+
var type = obj.GetType();
55+
bool isToStringableObject = false;
56+
while (type != null)
57+
{
58+
if (type.FullName == "Newtonsoft.Json.Linq.JToken")
59+
{
60+
isToStringableObject = true;
61+
break;
62+
}
63+
type = type.BaseType;
64+
}
65+
if (isToStringableObject)
66+
return obj.ToString();
67+
68+
return JsonSerializer.Serialize(obj, options);
69+
70+
}
71+
4872
static void NormalizePropertyOrder(JsonElement e, Utf8JsonWriter output)
4973
{
5074
if (e.ValueKind == JsonValueKind.Object)

src/OutputChecker.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace CheckTestOutput
1010
{
1111
public class OutputChecker
1212
{
13+
/// <summary> Checks that the provided test output matched a file from the <paramref name="directory"/>. Filename is a {callingClass}.{callingMethod}.fileExtension </summary>
1314
/// <param name="directory">Directory with the reference outputs, relative to the <see cref="calledFrom"/> parameter.</param>
1415
/// <param name="sanitizeGuids">Replace all strings that look like Guid by a sequential id. The sanitization preserves equality.</param>
1516
/// <param name="sanitizeQuotedGuids">Replace all strings that look like Guid and are in quotes by a sequential id. The sanitization preserves equality.</param>
@@ -142,6 +143,7 @@ private bool IsModified(string file)
142143
return !gitOut.All(string.IsNullOrEmpty);
143144
}
144145

146+
/// <summary> Applies the <see cref="NonDeterminismSanitizers" /> to the string. </summary>
145147
public string SanitizeString(string outputString)
146148
{
147149
var x = new Dictionary<string, string>();
@@ -192,11 +194,11 @@ internal void CheckOutputCore(string outputString, string checkName, string meth
192194
{
193195
var diff = RunGitCommand("diff", filename);
194196
if (diff.All(string.IsNullOrEmpty))
195-
throw new Exception($"{Path.GetFileName(filename)} is not explicitly accepted - the file is untracked in git. View the file and stage to let this test pass. Confused? See https://github.com/exyi/CheckTestOutput/blob/master/trouble.md#untracked-file\n");
197+
throw new Exception($"{Path.GetFileName(filename)} is not explicitly accepted - the file is untracked in git. To let this test pass, view the file and stage it. Confused? See https://github.com/exyi/CheckTestOutput/blob/master/trouble.md#untracked-file\n");
196198
throw new Exception(
197199
$"{Path.GetFileName(filename)} has changed, the actual output differs from the previous accepted output:\n\n" +
198200
string.Join("\n", diff) + "\n\n" +
199-
"If this change OK? Stage the file in git to let the test pass. Confused? See https://github.com/exyi/CheckTestOutput/blob/master/trouble.md#changed-file\n"
201+
"If this change OK? To let the test pass, stage the file in git. Confused? See https://github.com/exyi/CheckTestOutput/blob/master/trouble.md#changed-file\n"
200202

201203
);
202204
}

0 commit comments

Comments
 (0)