/// <summary> /// Parses the Json and compares expected to actual. /// </summary> /// <param name="expected">The expected Json</param> /// <param name="actual">The actual Json</param> /// <param name="options">How to compare the Json</param> public static void Equal(string expected, string actual, JsonAssertOptions options = JsonAssertOptions.Default) { var expectedJson = ParseDocument(expected, nameof(expected), options); var actualJson = ParseDocument(actual, nameof(actual), options); Equal(expectedJson, actualJson, null, options); }
/// <summary> /// 1 Serializes <paramref name="actual"/> to an Json string using <see cref="JsonSerializer"/> /// 2 Compares the Json with <paramref name="expectedJson"/> /// 3 Creates a <see cref="ContainerClass{T}"/> /// 4 Serializes it to Json. /// 5 Compares the Json /// 6 Deserializes it to container class /// 7 Does 2 & 3 again, we repeat this to catch any errors from deserializing /// 8 Returns roundtripped instance /// </summary> /// <typeparam name="T">The type</typeparam> /// <param name="expectedJson">The expected Json</param> /// <param name="actual">The actual item</param> /// <param name="options">How to compare the Json</param> /// <returns>The roundtripped instance</returns> public static T Equal <T>(string expectedJson, T actual, JsonAssertOptions options = JsonAssertOptions.Verbatim) { var actualJson = ToJson(actual, nameof(actual), null); JsonAssert.Equal(expectedJson, actualJson, options); return(Roundtrip(actual)); }
private static void Equal(JTokenAndSource expected, JTokenAndSource actual, IEqualityComparer<JValue> comparer, JsonAssertOptions options) { var expectedToken = expected?.JToken; var actualToken = actual?.JToken; if (expectedToken?.Type != actualToken?.Type) { var message = CreateMessage(expected, actual); throw new AssertException(message); } CheckElementOrder(expected, actual, options); if (expected?.JProperty?.Name != actual?.JProperty?.Name) { var message = CreateMessage(expected, actual); throw new AssertException(message); } var expectedValue = expectedToken as JValue; var actualValue = actualToken as JValue; if (expectedValue != null || actualValue != null) { if (expectedValue == null || actualValue == null) { var message = CreateMessage(expected, actual); throw new AssertException(message); } if (actualValue.HasValues) { var message = CreateMessage(expected, actual); throw new AssertException(message); } var valueComparer = JValueComparer.GetFor(options); if (valueComparer.Equals(expectedValue, actualValue)) { return; } if (comparer?.Equals(expectedValue, actualValue) == true) { return; } else { var message = CreateMessage(expected, actual); throw new AssertException(message); } } for (int i = 0; i < Math.Max(expected?.Children.Count ?? 0, actual?.Children.Count ?? 0); i++) { var expectedChild = expected?.Children.ElementAtOrDefault(i); var actualChild = actual?.Children.ElementAtOrDefault(i); Equal(expectedChild, actualChild, comparer, options); } }
/// <summary> /// Parses the Json and compares expected to actual. /// </summary> /// <param name="expected">The expected Json</param> /// <param name="actual">The actual Json</param> /// <param name="valueComparer">For custom value comparison.</param> /// <param name="options">How to compare the Json</param> public static void Equal( string expected, string actual, IEqualityComparer<JValue> valueComparer, JsonAssertOptions options = JsonAssertOptions.Verbatim) { var expectedJson = ParseDocument(expected, nameof(expected), options); var actualJson = ParseDocument(actual, nameof(actual), options); Equal(expectedJson, actualJson, valueComparer, options); }
public JTokenAndSource(string json, JToken jObject, JsonAssertOptions options) { this.Json = json; this.JToken = jObject; this.Options = options; var children = jObject.Children().Select(x => new JTokenAndSource(json, x, options)); this.Children = options == JsonAssertOptions.Verbatim ? children.ToList() : children.OrderBy(x => x.PropertyName).ToList(); }
/// <summary> /// Parses the Json and compares expected to actual. /// </summary> /// <param name="expected">The expected Json</param> /// <param name="actual">The actual Json</param> /// <param name="valueComparer">For custom value comparison.</param> /// <param name="options">How to compare the Json</param> public static void Equal( string expected, string actual, IEqualityComparer <JValue> valueComparer, JsonAssertOptions options = JsonAssertOptions.Verbatim) { var expectedJson = ParseDocument(expected, nameof(expected), options); var actualJson = ParseDocument(actual, nameof(actual), options); Equal(expectedJson, actualJson, valueComparer, options); }
private static JTokenAndSource ParseDocument(string json, string parameterName, JsonAssertOptions options) { try { var jObject = JToken.Parse(json); return new JTokenAndSource(json, jObject, options); } catch (Exception e) { throw AssertException.CreateFromException($"{parameterName} is not valid Json.", e); } }
private static void CheckElementOrder(JTokenAndSource expected, JTokenAndSource actual, JsonAssertOptions options) { if (!options.HasFlag(JsonAssertOptions.Verbatim) || expected == null || actual == null) { return; } for (int i = 0; i < Math.Min(expected.Children.Count, actual.Children.Count); i++) { if (expected.Children[i].JProperty?.Name != actual.Children[i].JProperty?.Name && actual.Children.Any(x => x.JProperty?.Name == expected.Children[i].JProperty?.Name)) { var message = CreateMessage(expected.Children[i], actual.Children[i], " The order of elements is incorrect."); throw new AssertException(message); } } }
public static JValueComparer GetFor(JsonAssertOptions options) { return(Cache.GetOrAdd(options, x => new JValueComparer(x))); }
public JValueComparer(JsonAssertOptions options) { this.options = options; }
private static void Equal(JTokenAndSource expected, JTokenAndSource actual, IEqualityComparer <JValue> comparer, JsonAssertOptions options) { var expectedToken = expected?.JToken; var actualToken = actual?.JToken; if (expectedToken?.Type != actualToken?.Type) { var message = CreateMessage(expected, actual); throw new AssertException(message); } CheckElementOrder(expected, actual, options); if (expected?.JProperty?.Name != actual?.JProperty?.Name) { var message = CreateMessage(expected, actual); throw new AssertException(message); } var expectedValue = expectedToken as JValue; var actualValue = actualToken as JValue; if (expectedValue != null || actualValue != null) { if (expectedValue == null || actualValue == null) { var message = CreateMessage(expected, actual); throw new AssertException(message); } if (actualValue.HasValues) { var message = CreateMessage(expected, actual); throw new AssertException(message); } var valueComparer = JValueComparer.GetFor(options); if (valueComparer.Equals(expectedValue, actualValue)) { return; } if (comparer?.Equals(expectedValue, actualValue) == true) { return; } else { var message = CreateMessage(expected, actual); throw new AssertException(message); } } for (int i = 0; i < Math.Max(expected?.Children.Count ?? 0, actual?.Children.Count ?? 0); i++) { var expectedChild = expected?.Children.ElementAtOrDefault(i); var actualChild = actual?.Children.ElementAtOrDefault(i); Equal(expectedChild, actualChild, comparer, options); } }
private static JTokenAndSource ParseDocument(string json, string parameterName, JsonAssertOptions options) { try { var jObject = JToken.Parse(json); return(new JTokenAndSource(json, jObject, options)); } catch (Exception e) { throw AssertException.CreateFromException($"{parameterName} is not valid Json.", e); } }