using System; using System.Collections; using UnitTests.Common.Utils; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace UnitTests.Common.Extensions { [TestClass] [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class JsonExtensionsTests { [TestMethod] public void ShouldReturnJson() { // arrange var testObject = new JsonTestClass(); string expected = @"{""stringValue"":""Hello World!"",""isBoolTrue"":true,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":42.21,""localTimestamp"":""2021-11-16T20:15:34+01:00"",""utcTimestamp"":""2021-11-16T20:15:34Z"",""object"":{""integerValue"":42,""stringValue"":""Foo-Bar""}}"; // act string json = testObject.SerializeJson(); // assert Assert.IsFalse(string.IsNullOrWhiteSpace(json)); Assert.AreEqual(expected, json); } [TestMethod] public void ShouldReturnJsonIndented() { // arrange var testObject = new JsonTestClass(); string expected = @"{ ""stringValue"": ""Hello World!"", ""isBoolTrue"": true, ""floatValue"": 12.34, ""doubleValue"": 21.42, ""decimalValue"": 42.21, ""localTimestamp"": ""2021-11-16T20:15:34+01:00"", ""utcTimestamp"": ""2021-11-16T20:15:34Z"", ""object"": { ""integerValue"": 42, ""stringValue"": ""Foo-Bar"" } }"; // act string json = testObject.SerializeJson(indented: true); // assert Assert.IsFalse(string.IsNullOrWhiteSpace(json)); Assert.AreEqual(expected.Replace("\r", ""), json.Replace("\r", "")); } [TestMethod] public void ShouldReturnJsonWithSingleQuotes() { // arrange var testObject = new JsonTestClass { StringValue = "Sam's Pub" }; string expected = "{'stringValue':'Sam\\'s Pub','isBoolTrue':true,'floatValue':12.34,'doubleValue':21.42,'decimalValue':42.21,'localTimestamp':'2021-11-16T20:15:34+01:00','utcTimestamp':'2021-11-16T20:15:34Z','object':{'integerValue':42,'stringValue':'Foo-Bar'}}"; // act string json = testObject.SerializeJson(useSingleQuotes: true); // assert Assert.IsFalse(string.IsNullOrWhiteSpace(json)); Assert.AreEqual(expected, json); } [TestMethod] public void ShouldReturnJsonWithoutCamelCase() { // arrange var testObject = new JsonTestClass(); string expected = @"{""StringValue"":""Hello World!"",""IsBoolTrue"":true,""FloatValue"":12.34,""DoubleValue"":21.42,""DecimalValue"":42.21,""LocalTimestamp"":""2021-11-16T20:15:34+01:00"",""UtcTimestamp"":""2021-11-16T20:15:34Z"",""Object"":{""IntegerValue"":42,""StringValue"":""Foo-Bar""}}"; // act string json = testObject.SerializeJson(useCamelCase: false); // assert Assert.IsFalse(string.IsNullOrWhiteSpace(json)); Assert.AreEqual(expected, json); } [TestMethod] public void ShouldReturnJsonWithType() { // arrange var testObject = new JsonTestClass(); string expected = @"{""$type"":""UnitTests.Common.Utils.JsonTestClass, UnitTests"",""stringValue"":""Hello World!"",""isBoolTrue"":true,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":42.21,""localTimestamp"":""2021-11-16T20:15:34+01:00"",""utcTimestamp"":""2021-11-16T20:15:34Z"",""object"":{""$type"":""UnitTests.Common.Utils.JsonTestSubClass, UnitTests"",""integerValue"":42,""stringValue"":""Foo-Bar""}}"; // act string json = testObject.SerializeJson(includeType: true); // assert Assert.IsFalse(string.IsNullOrWhiteSpace(json)); Assert.AreEqual(expected, json); } [TestMethod] public void ShouldDeserializeWithoutFallback() { // arrange string workingJson = @"{""stringValue"":""Some fancy string"",""isBoolTrue"":false,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":123.45,""localTimestamp"":""2021-11-15T20:15:34+01:00"",""utcTimestamp"":""2021-10-16T20:15:34Z"",""object"":{""integerValue"":21,""stringValue"":""FooBar""}}"; string brokenJson = @"{""strValue"":""Some fancy string"",""isBoolTrue"":false,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":123.45,""localTimestamp"":""2021-11-15T20:15:34+01:00"",""utcTimestamp"":""2021-10-16T20:15:34Z"",""object"":{""integerValue"":21.12,""stringValue"":""FooBar""}}"; string emptyString = ""; // act var workingObj = workingJson.DeserializeJson(); var emptyObj = emptyString.DeserializeJson(); try { var brokenObj = brokenJson.DeserializeJson(); Assert.Fail(); } catch (JsonReaderException) { } // assert Assert.IsNotNull(workingObj); Assert.IsNull(emptyObj); Assert.AreEqual("Some fancy string", workingObj.StringValue); Assert.IsFalse(workingObj.IsBoolTrue); Assert.AreEqual(123.45m, workingObj.DecimalValue); Assert.AreEqual(DateTimeKind.Local, workingObj.LocalTimestamp.Kind); Assert.AreEqual("15.11.2021 20:15:34", workingObj.LocalTimestamp.ToString("dd.MM.yyyy HH:mm:ss")); Assert.AreEqual(DateTimeKind.Utc, workingObj.UtcTimestamp.Kind); Assert.AreEqual("16.10.2021 20:15:34", workingObj.UtcTimestamp.ToString("dd.MM.yyyy HH:mm:ss")); } [TestMethod] public void ShouldDeserializeWithFallback() { // arrange string workingJson = @"{""stringValue"":""Some fancy string"",""isBoolTrue"":false,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":123.45,""localTimestamp"":""2021-11-15T20:15:34+01:00"",""utcTimestamp"":""2021-10-16T20:15:34Z"",""object"":{""integerValue"":21,""stringValue"":""FooBar""}}"; string brokenJson = @"{""strValue"":""Some fancy string"",""isBoolTrue"":false,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":123.45,""localTimestamp"":""2021-11-15T20:15:34+01:00"",""utcTimestamp"":""2021-10-16T20:15:34Z"",""object"":{""integerValue"":21.12,""stringValue"":""FooBar""}}"; string emptyString = ""; var fallback = new JsonTestClass { DoubleValue = 0.815 }; // act var workingObj = workingJson.DeserializeJson(fallback); var brokenObj = brokenJson.DeserializeJson(fallback); var emptyObj = emptyString.DeserializeJson(fallback); // assert Assert.IsNotNull(workingObj); Assert.IsNotNull(brokenObj); Assert.IsNull(emptyObj); Assert.AreEqual("Some fancy string", workingObj.StringValue); Assert.IsFalse(workingObj.IsBoolTrue); Assert.AreEqual(123.45m, workingObj.DecimalValue); Assert.AreEqual(21.42, workingObj.DoubleValue); Assert.AreEqual(DateTimeKind.Local, workingObj.LocalTimestamp.Kind); Assert.AreEqual("15.11.2021 20:15:34", workingObj.LocalTimestamp.ToString("dd.MM.yyyy HH:mm:ss")); Assert.AreEqual(DateTimeKind.Utc, workingObj.UtcTimestamp.Kind); Assert.AreEqual("16.10.2021 20:15:34", workingObj.UtcTimestamp.ToString("dd.MM.yyyy HH:mm:ss")); Assert.AreEqual(fallback.StringValue, brokenObj.StringValue); Assert.AreEqual(fallback.IsBoolTrue, brokenObj.IsBoolTrue); Assert.AreEqual(fallback.DecimalValue, brokenObj.DecimalValue); Assert.AreEqual(fallback.DoubleValue, brokenObj.DoubleValue); Assert.AreEqual(fallback.LocalTimestamp.Kind, brokenObj.LocalTimestamp.Kind); Assert.AreEqual(fallback.LocalTimestamp, brokenObj.LocalTimestamp); Assert.AreEqual(fallback.UtcTimestamp.Kind, brokenObj.UtcTimestamp.Kind); Assert.AreEqual(fallback.UtcTimestamp, brokenObj.UtcTimestamp); } [TestMethod] public void ShouldDeserializeUsingPopulate() { // arrange string json = @"{""stringValue"":""Some fancy string"",""isBoolTrue"":false,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":123.45,""localTimestamp"":""2021-11-15T20:15:34+01:00"",""utcTimestamp"":""2021-10-16T20:15:34Z"",""object"":{""integerValue"":21,""stringValue"":""FooBar""}}"; var obj = new JsonTestClass(); // act obj.DeserializeJson(json); // assert Assert.AreEqual("Some fancy string", obj.StringValue); Assert.IsFalse(obj.IsBoolTrue); Assert.AreEqual(123.45m, obj.DecimalValue); Assert.AreEqual(21.42, obj.DoubleValue); Assert.AreEqual(DateTimeKind.Local, obj.LocalTimestamp.Kind); Assert.AreEqual("15.11.2021 20:15:34", obj.LocalTimestamp.ToString("dd.MM.yyyy HH:mm:ss")); Assert.AreEqual(DateTimeKind.Utc, obj.UtcTimestamp.Kind); Assert.AreEqual("16.10.2021 20:15:34", obj.UtcTimestamp.ToString("dd.MM.yyyy HH:mm:ss")); } [TestMethod] public void ShouldConvertToJObject() { // arrange var obj = new JsonTestClass { StringValue = "Hello JSON", DecimalValue = 0.815m }; // act var jObj = obj.ConvertToJObject(); // assert Assert.IsNotNull(jObj); Assert.AreEqual(typeof(JObject), jObj.GetType()); Assert.AreEqual(obj.StringValue, jObj.Value("stringValue")); Assert.AreEqual(obj.DecimalValue, jObj.Value("decimalValue")); Assert.AreEqual(obj.LocalTimestamp.Kind, jObj.Value("localTimestamp").Kind); Assert.AreEqual(obj.LocalTimestamp, jObj.Value("localTimestamp")); Assert.AreEqual(obj.UtcTimestamp.Kind, jObj.Value("utcTimestamp").Kind); Assert.AreEqual(obj.UtcTimestamp, jObj.Value("utcTimestamp")); } [TestMethod] public void ShouldConvertToJArray() { // arrange string[] stringArray = new[] { "one", "two", "three" }; var objectArray = new[] { new JsonTestClass { StringValue = "One" }, new JsonTestClass { StringValue = "Two" }, new JsonTestClass { StringValue = "Three" } }; // act var stringJArray = stringArray.ConvertToJArray(); var objectJArray = objectArray.ConvertToJArray(); // assert Assert.IsNotNull(stringJArray); Assert.AreEqual(typeof(JArray), stringJArray.GetType()); Assert.AreEqual(stringArray[0], stringJArray[0]); Assert.AreEqual(stringArray[1], stringJArray[1]); Assert.AreEqual(stringArray[2], stringJArray[2]); Assert.IsNotNull(objectJArray); Assert.AreEqual(typeof(JArray), objectJArray.GetType()); Assert.AreEqual(objectArray[0].StringValue, objectJArray[0].Value("stringValue")); Assert.AreEqual(objectArray[1].StringValue, objectJArray[1].Value("stringValue")); Assert.AreEqual(objectArray[2].StringValue, objectJArray[2].Value("stringValue")); } [TestMethod] public void ShouldRunJsonTreeWithoutDefault() { // arrange var obj = new JsonTestClass { StringValue = "Running Json", Object = new JsonTestSubClass { IntegerValue = 4711 } }; var jObj = obj.ConvertToJObject(); // act string topLevelString = jObj.GetValue("stringValue"); decimal topLevelDecimal = jObj.GetValue("decimalValue"); int subLevelInteger = jObj.GetValue("object:integerValue"); string subLevelString = jObj.GetValue("object:stringValue"); string notExistingOnTopLevel = jObj.GetValue("fancyValue"); string notExistingOnSubLevel = jObj.GetValue("object:fancyValue"); int? notExistingLevel = jObj.GetValue("fancy:int"); // assert Assert.AreEqual(obj.StringValue, topLevelString); Assert.AreEqual(obj.DecimalValue, topLevelDecimal); Assert.AreEqual(obj.Object.IntegerValue, subLevelInteger); Assert.AreEqual(obj.Object.StringValue, subLevelString); Assert.IsNull(notExistingOnTopLevel); Assert.IsNull(notExistingOnSubLevel); Assert.IsNull(notExistingLevel); } [TestMethod] public void ShouldRunJsonTreeWithDefault() { // arrange var obj = new JsonTestClass { StringValue = "Running Json", Object = new JsonTestSubClass { IntegerValue = 4711 } }; var jObj = obj.ConvertToJObject(); // act string topLevelString = jObj.GetValue("stringValue", "Test String"); decimal topLevelDecimal = jObj.GetValue("decimalValue", 13.24m); int subLevelInteger = jObj.GetValue("object:integerValue", 55); string subLevelString = jObj.GetValue("object:stringValue", "Yeah!"); string notExistingOnTopLevel = jObj.GetValue("fancyValue", "Party!"); string notExistingOnSubLevel = jObj.GetValue("object:fancyValue", "Well Done"); int? notExistingLevel = jObj.GetValue("fancy:int", 13); // assert Assert.AreEqual(obj.StringValue, topLevelString); Assert.AreEqual(obj.DecimalValue, topLevelDecimal); Assert.AreEqual(obj.Object.IntegerValue, subLevelInteger); Assert.AreEqual(obj.Object.StringValue, subLevelString); Assert.AreEqual("Party!", notExistingOnTopLevel); Assert.AreEqual("Well Done", notExistingOnSubLevel); Assert.AreEqual(13, notExistingLevel); } [TestMethod] public void ShouldReturnNull() { // arrange object obj = null; IEnumerable list = null; JObject jObj = null; // act var objTest = obj.ConvertToJObject(); var listTest = list.ConvertToJArray(); object getTest = jObj.GetValue("Nothing"); // assert Assert.IsNull(objTest); Assert.IsNull(listTest); Assert.IsNull(getTest); } [TestMethod] public void ShouldHandleSerializationError() { // arrange var obj = new JsonErrorClass(); // act string json = obj.SerializeJson(); // assert Assert.AreEqual("{}", json); } } }