@@ -119,11 +119,28 @@ private static List<string> CompareObjects(object expected, object actual, Prope
119119 continue ;
120120 }
121121
122+ Type propType = property . PropertyType ;
123+
124+ // 🔥 Special case: if it's object or anonymous, compare via JSON string
125+ if ( propType == typeof ( object ) || IsAnonymousType ( expectedValue . GetType ( ) ) || IsAnonymousType ( actualValue . GetType ( ) ) )
126+ {
127+ var expectedJson = JsonSerializer . Serialize ( expectedValue ) ;
128+ var actualJson = JsonSerializer . Serialize ( actualValue ) ;
129+
130+ if ( expectedJson != actualJson )
131+ {
132+ differences . Add ( $ " - ❌ { path } .{ property . Name } : Expected JSON **[{ expectedJson } ]**, but got **[{ actualJson } ]**.") ;
133+ }
134+
135+ continue ;
136+ }
137+
138+ // 💡 Deep compare if complex
122139 if ( ! expectedValue . Equals ( actualValue ) )
123140 {
124- if ( PropertyMappingCache . IsComplexType ( property . PropertyType ) )
141+ if ( PropertyMappingCache . IsComplexType ( propType ) )
125142 {
126- var nestedProperties = property . PropertyType . GetProperties ( BindingFlags . Public | BindingFlags . Instance )
143+ var nestedProperties = propType . GetProperties ( BindingFlags . Public | BindingFlags . Instance )
127144 . Where ( prop => ! Attribute . IsDefined ( prop , typeof ( MagicNotMappedAttribute ) ) )
128145 . ToArray ( ) ;
129146
@@ -139,5 +156,13 @@ private static List<string> CompareObjects(object expected, object actual, Prope
139156
140157 return differences ;
141158 }
159+ private static bool IsAnonymousType ( Type type )
160+ {
161+ return Attribute . IsDefined ( type , typeof ( System . Runtime . CompilerServices . CompilerGeneratedAttribute ) )
162+ && type . IsGenericType
163+ && type . Name . Contains ( "AnonymousType" )
164+ && ( type . Name . StartsWith ( "<>" ) || type . Name . StartsWith ( "VB$" ) )
165+ && type . Namespace == null ;
166+ }
142167 }
143168}
0 commit comments