@@ -7,6 +7,33 @@ namespace Immutable.Audience.Tests
77 [ TestFixture ]
88 public class JsonTests
99 {
10+ // Per-scenario fixture keys/values for the serialise tests.
11+ private const string BoolFixtureKey = "flag" ;
12+ private const string NumericFixtureKey = "n" ;
13+ private const string NullFixtureKey = "x" ;
14+ private const string VShortFixture = "v" ;
15+ private const string ArrayFixtureKey = "items" ;
16+
17+ // RealisticEventPayload: nested keys and arrays exercise nested-list serialisation.
18+ private const string PropLevelKey = "level" ;
19+ private const string PropScoreKey = "score" ;
20+ private const string PropPerfectKey = "perfect" ;
21+ private const string PropTagsKey = "tags" ;
22+ private const string TagFastValue = "fast" ;
23+ private const string TagCleanValue = "clean" ;
24+
25+ // Cycle / depth guard fixtures.
26+ private const string DeepNestNextKey = "next" ;
27+ private const string SelfRefKey = "self" ;
28+ private const string CycleErrorMarker = "cycle" ;
29+ private const string NestingExceedsErrorMarker = "nesting exceeds" ;
30+
31+ // Diamond scenario (shared child under sibling keys is NOT a cycle).
32+ private const string DiamondInnerKey = "k" ;
33+ private const string DiamondInnerValue = "v" ;
34+ private const string DiamondLeftKey = "a" ;
35+ private const string DiamondRightKey = "b" ;
36+
1037 [ Test ]
1138 public void Serialize_EmptyDict_ReturnsEmptyObject ( )
1239 {
@@ -41,41 +68,41 @@ public void Serialize_StringWithSpecialChars_EscapesCorrectly()
4168 [ Test ]
4269 public void Serialize_BoolTrue_ReturnsLowercaseTrue ( )
4370 {
44- var data = new Dictionary < string , object > { { "flag" , true } } ;
71+ var data = new Dictionary < string , object > { { BoolFixtureKey , true } } ;
4572
46- Assert . AreEqual ( "{ \" flag \" :true}", Json . Serialize ( data ) ) ;
73+ Assert . AreEqual ( $ "{{ \" { BoolFixtureKey } \" :true} }", Json . Serialize ( data ) ) ;
4774 }
4875
4976 [ Test ]
5077 public void Serialize_BoolFalse_ReturnsLowercaseFalse ( )
5178 {
52- var data = new Dictionary < string , object > { { "flag" , false } } ;
79+ var data = new Dictionary < string , object > { { BoolFixtureKey , false } } ;
5380
54- Assert . AreEqual ( "{ \" flag \" :false}", Json . Serialize ( data ) ) ;
81+ Assert . AreEqual ( $ "{{ \" { BoolFixtureKey } \" :false} }", Json . Serialize ( data ) ) ;
5582 }
5683
5784 [ Test ]
5885 public void Serialize_IntValue_ReturnsIntegerLiteral ( )
5986 {
60- var data = new Dictionary < string , object > { { "n" , 42 } } ;
87+ var data = new Dictionary < string , object > { { NumericFixtureKey , 42 } } ;
6188
62- Assert . AreEqual ( "{ \" n \" :42}", Json . Serialize ( data ) ) ;
89+ Assert . AreEqual ( $ "{{ \" { NumericFixtureKey } \" :42} }", Json . Serialize ( data ) ) ;
6390 }
6491
6592 [ Test ]
6693 public void Serialize_LongValue_ReturnsIntegerLiteral ( )
6794 {
68- var data = new Dictionary < string , object > { { "n" , 9876543210L } } ;
95+ var data = new Dictionary < string , object > { { NumericFixtureKey , 9876543210L } } ;
6996
70- Assert . AreEqual ( "{ \" n \" :9876543210}", Json . Serialize ( data ) ) ;
97+ Assert . AreEqual ( $ "{{ \" { NumericFixtureKey } \" :9876543210} }", Json . Serialize ( data ) ) ;
7198 }
7299
73100 [ Test ]
74101 public void Serialize_NullValue_ReturnsJsonNull ( )
75102 {
76- var data = new Dictionary < string , object > { { "x" , null } } ;
103+ var data = new Dictionary < string , object > { { NullFixtureKey , null } } ;
77104
78- Assert . AreEqual ( "{ \" x \" :null}", Json . Serialize ( data ) ) ;
105+ Assert . AreEqual ( $ "{{ \" { NullFixtureKey } \" :null} }", Json . Serialize ( data ) ) ;
79106 }
80107
81108 [ Test ]
@@ -97,47 +124,47 @@ public void Serialize_NestedDict_ReturnsNestedObject()
97124 [ Test ]
98125 public void Serialize_FloatNaN_SerializesAsNull ( )
99126 {
100- Assert . AreEqual ( "{ \" v \" :null}", Json . Serialize ( new Dictionary < string , object > { { "v" , float . NaN } } ) ) ;
127+ Assert . AreEqual ( $ "{{ \" { VShortFixture } \" :null}} ", Json . Serialize ( new Dictionary < string , object > { { VShortFixture , float . NaN } } ) ) ;
101128 }
102129
103130 [ Test ]
104131 public void Serialize_FloatPositiveInfinity_SerializesAsNull ( )
105132 {
106- Assert . AreEqual ( "{ \" v \" :null}", Json . Serialize ( new Dictionary < string , object > { { "v" , float . PositiveInfinity } } ) ) ;
133+ Assert . AreEqual ( $ "{{ \" { VShortFixture } \" :null}} ", Json . Serialize ( new Dictionary < string , object > { { VShortFixture , float . PositiveInfinity } } ) ) ;
107134 }
108135
109136 [ Test ]
110137 public void Serialize_FloatNegativeInfinity_SerializesAsNull ( )
111138 {
112- Assert . AreEqual ( "{ \" v \" :null}", Json . Serialize ( new Dictionary < string , object > { { "v" , float . NegativeInfinity } } ) ) ;
139+ Assert . AreEqual ( $ "{{ \" { VShortFixture } \" :null}} ", Json . Serialize ( new Dictionary < string , object > { { VShortFixture , float . NegativeInfinity } } ) ) ;
113140 }
114141
115142 [ Test ]
116143 public void Serialize_DoubleNaN_SerializesAsNull ( )
117144 {
118- Assert . AreEqual ( "{ \" v \" :null}", Json . Serialize ( new Dictionary < string , object > { { "v" , double . NaN } } ) ) ;
145+ Assert . AreEqual ( $ "{{ \" { VShortFixture } \" :null}} ", Json . Serialize ( new Dictionary < string , object > { { VShortFixture , double . NaN } } ) ) ;
119146 }
120147
121148 [ Test ]
122149 public void Serialize_DoubleInfinity_SerializesAsNull ( )
123150 {
124- Assert . AreEqual ( "{ \" v \" :null}", Json . Serialize ( new Dictionary < string , object > { { "v" , double . PositiveInfinity } } ) ) ;
151+ Assert . AreEqual ( $ "{{ \" { VShortFixture } \" :null}} ", Json . Serialize ( new Dictionary < string , object > { { VShortFixture , double . PositiveInfinity } } ) ) ;
125152 }
126153
127154 [ Test ]
128155 public void Serialize_FloatValue_NormalRange ( )
129156 {
130- var data = new Dictionary < string , object > { { "v" , 3.14f } } ;
157+ var data = new Dictionary < string , object > { { VShortFixture , 3.14f } } ;
131158 var result = Json . Serialize ( data ) ;
132- StringAssert . Contains ( "\" v \" :" , result ) ;
133- StringAssert . DoesNotContain ( "\" v \" :\" " , result ) ; // must not be quoted
159+ StringAssert . Contains ( $ "\" { VShortFixture } \" :", result ) ;
160+ StringAssert . DoesNotContain ( $ "\" { VShortFixture } \" :\" ", result ) ;
134161 }
135162
136163 [ Test ]
137164 public void Serialize_FloatValue_LargeExponent_PreservesValue ( )
138165 {
139166 // 1e30f in scientific notation is valid JSON; must not be silently zeroed
140- var data = new Dictionary < string , object > { { "v" , 1e30f } } ;
167+ var data = new Dictionary < string , object > { { VShortFixture , 1e30f } } ;
141168 var result = Json . Serialize ( data ) ;
142169 var serialised = result . Substring ( result . IndexOf ( ':' ) + 1 , result . Length - result . IndexOf ( ':' ) - 2 ) ;
143170 Assert . AreNotEqual ( "0" , serialised ) ;
@@ -148,7 +175,7 @@ public void Serialize_FloatValue_LargeExponent_PreservesValue()
148175 public void Serialize_FloatValue_SmallNegativeExponent_PreservesValue ( )
149176 {
150177 // 1e-30f: the old F6 fallback turned this into "0.000000"
151- var data = new Dictionary < string , object > { { "v" , 1e-30f } } ;
178+ var data = new Dictionary < string , object > { { VShortFixture , 1e-30f } } ;
152179 var result = Json . Serialize ( data ) ;
153180 var serialised = result . Substring ( result . IndexOf ( ':' ) + 1 , result . Length - result . IndexOf ( ':' ) - 2 ) ;
154181 Assert . AreNotEqual ( "0" , serialised ) ;
@@ -158,7 +185,7 @@ public void Serialize_FloatValue_SmallNegativeExponent_PreservesValue()
158185 [ Test ]
159186 public void Serialize_DoubleValue_SmallNegativeExponent_PreservesValue ( )
160187 {
161- var data = new Dictionary < string , object > { { "v" , 1e-300 } } ;
188+ var data = new Dictionary < string , object > { { VShortFixture , 1e-300 } } ;
162189 var result = Json . Serialize ( data ) ;
163190 var serialised = result . Substring ( result . IndexOf ( ':' ) + 1 , result . Length - result . IndexOf ( ':' ) - 2 ) ;
164191 Assert . AreNotEqual ( "0" , serialised ) ;
@@ -170,10 +197,10 @@ public void Serialize_ListValue_ReturnsJsonArray()
170197 {
171198 var data = new Dictionary < string , object >
172199 {
173- { "items" , new List < object > { "a" , 1 , true } }
200+ { ArrayFixtureKey , new List < object > { TestEventNames . PlaceholderA , 1 , true } }
174201 } ;
175202
176- Assert . AreEqual ( "{ \" items \" :[\" a \" ,1,true]}", Json . Serialize ( data ) ) ;
203+ Assert . AreEqual ( $ "{{ \" { ArrayFixtureKey } \" :[\" { TestEventNames . PlaceholderA } \" ,1,true]} }", Json . Serialize ( data ) ) ;
177204 }
178205
179206 [ Test ]
@@ -187,22 +214,22 @@ public void Serialize_RealisticEventPayload_ProducesCorrectJson()
187214 { MessageFields . UserId , null } ,
188215 { MessageFields . Properties , new Dictionary < string , object >
189216 {
190- { "level" , 5 } ,
191- { "score" , 9800L } ,
192- { "perfect" , true } ,
193- { "tags" , new List < object > { "fast" , "clean" } }
217+ { PropLevelKey , 5 } ,
218+ { PropScoreKey , 9800L } ,
219+ { PropPerfectKey , true } ,
220+ { PropTagsKey , new List < object > { TagFastValue , TagCleanValue } }
194221 }
195222 }
196223 } ;
197224
198225 var result = Json . Serialize ( data ) ;
199226
200227 StringAssert . Contains ( $ "\" { MessageFields . Type } \" :\" { MessageTypes . Track } \" ", result ) ;
201- StringAssert . Contains ( $ "\" { MessageFields . EventName } \" :\" level_complete \" ", result ) ;
228+ StringAssert . Contains ( $ "\" { MessageFields . EventName } \" :\" { TestEventNames . LevelComplete } \" ", result ) ;
202229 StringAssert . Contains ( $ "\" { MessageFields . UserId } \" :null", result ) ;
203- StringAssert . Contains ( "\" level \" :5" , result ) ;
204- StringAssert . Contains ( "\" perfect \" :true" , result ) ;
205- StringAssert . Contains ( "\" tags \" :[\" fast \" ,\" clean \" ]" , result ) ;
230+ StringAssert . Contains ( $ "\" { PropLevelKey } \" :5", result ) ;
231+ StringAssert . Contains ( $ "\" { PropPerfectKey } \" :true", result ) ;
232+ StringAssert . Contains ( $ "\" { PropTagsKey } \" :[\" { TagFastValue } \" ,\" { TagCleanValue } \" ]", result ) ;
206233 }
207234
208235 [ Test ]
@@ -213,39 +240,39 @@ public void Serialize_NestingExceedsMaxDepth_ThrowsFormatException()
213240 for ( var i = 0 ; i < Json . MaxDepth ; i ++ )
214241 {
215242 var next = new Dictionary < string , object > ( ) ;
216- current [ "next" ] = next ;
243+ current [ DeepNestNextKey ] = next ;
217244 current = next ;
218245 }
219246
220247 var ex = Assert . Throws < FormatException > ( ( ) => Json . Serialize ( root ) ) ;
221- StringAssert . Contains ( "nesting exceeds" , ex . Message ) ;
248+ StringAssert . Contains ( NestingExceedsErrorMarker , ex . Message ) ;
222249 }
223250
224251 [ Test ]
225252 public void Serialize_SelfReferentialDict_ThrowsFormatException ( )
226253 {
227254 var root = new Dictionary < string , object > ( ) ;
228- root [ "self" ] = root ;
255+ root [ SelfRefKey ] = root ;
229256
230257 var ex = Assert . Throws < FormatException > ( ( ) => Json . Serialize ( root ) ) ;
231- StringAssert . Contains ( "cycle" , ex . Message ) ;
258+ StringAssert . Contains ( CycleErrorMarker , ex . Message ) ;
232259 }
233260
234261 [ Test ]
235262 public void Serialize_SharedChildInSiblingKeys_IsNotTreatedAsCycle ( )
236263 {
237264 // Diamond: visited set tracks the current recursion stack, not all objects ever seen.
238- var shared = new Dictionary < string , object > { [ "k" ] = "v" } ;
265+ var shared = new Dictionary < string , object > { [ DiamondInnerKey ] = DiamondInnerValue } ;
239266 var root = new Dictionary < string , object >
240267 {
241- [ "a" ] = shared ,
242- [ "b" ] = shared ,
268+ [ DiamondLeftKey ] = shared ,
269+ [ DiamondRightKey ] = shared ,
243270 } ;
244271
245272 var result = Json . Serialize ( root ) ;
246273
247- StringAssert . Contains ( "\" a \" :{\" k \" :\" v \" }" , result ) ;
248- StringAssert . Contains ( "\" b \" :{\" k \" :\" v \" }" , result ) ;
274+ StringAssert . Contains ( $ "\" { DiamondLeftKey } \" :{{ \" { DiamondInnerKey } \" :\" { DiamondInnerValue } \" } }", result ) ;
275+ StringAssert . Contains ( $ "\" { DiamondRightKey } \" :{{ \" { DiamondInnerKey } \" :\" { DiamondInnerValue } \" } }", result ) ;
249276 }
250277 }
251278}
0 commit comments