Hello Corentin,

I took your code as base and improved it a bit to compare complex object: 

ClassMethod CompareObjects(expectedObject As %RegisteredObject, actualObject As %RegisteredObject) As %Status

{

        Set status= $$$OK

        Set returnValue = 1

       

        Try{

        // check if same class                                            

        Set className = $CLASSNAME(expectedObject)

        If (className '= $CLASSNAME(actualObject)) {

                Set returnValue = 0

                Set ^||differences(expectedObject,actualObject) = "not same class"

        }

        If (returnValue) {

            // Get the definition to browse properties

            Set classDef = ##class(%Library.ClassDefinition).%OpenId(className)

            Set propertiesDef = classDef.Properties

            // Check the value for each property

           

            For i = 1:1:propertiesDef.Count() {

                Set propertyName = propertiesDef.GetAt(i).Name

                Set propertyValueExpected = $PROPERTY(expectedObject,propertyName)

                Set propertyValueActual=$PROPERTY(actualObject,propertyName)

               

                // if different, supply the variable difference with the name of property + value



                If $ISOBJECT(propertyValueExpected){

                    If propertyValueExpected.%Extends("%Collection.Super"){

                        For ii=1:1:propertyValueExpected.Count(){

                            Set tSC= ..CompareObjects(propertyValueExpected.GetAt(ii),propertyValueActual.GetAt(ii))

                        }

                    }

                    Else{

                        Set tSC= ..CompareObjects(propertyValueExpected,propertyValueActual)

                    }

                }

                Else{

                    If ((propertyValueExpected '= "") && (propertyValueExpected '= propertyValueActual))

                    {                                                                                                              

                        Set ^||differences(expectedObject,propertyName)=propertyValueExpected _ " != " _ propertyValueActual

                    }

                }

                   

            }

       

        }

        }Catch e{

            Set status=e.AsStatus()

        }

         

        Quit status

}



ClassMethod AssertObjectEquals(expectedObject As %RegisteredObject, actualObject As %RegisteredObject, Output msg) As %Status

{

    Set status=$$$OK

    Set status=..CompareObjects(expectedObject,actualObject)


    If $DATA(^||differences){

        Set key=$ORDER(^||differences(""))

        Set key2=$ORDER(^||differences(key,""))

        Set msg=""

        While key'=""{

            While key2'=""{

                Set msg = msg_"; "_key2_": "_^||differences(key,key2)

                Set key2=$ORDER(^||differences(key,key2))

            }

            Set key=$ORDER(^||differences(key))

            Set:(key'="") key2=$ORDER(^||differences(key,""))

        }

        If $LENGTH(msg){

            Quit $$$ERROR(1,"Objects not equal")

        }

    }

    Quit status

}

 Please give me your opinion if there's anything to improve