Class UnitySerializedFieldAssertions
The assertion half of a "seed every field, force a rollback, assert it all comes back" test —
UnitySerializedFieldReflection enumerates the fields to walk, this compares what a restore
put back against what was captured. AssertRestored(string, object, object) dispatches on the VALUE's own shape
(a Unity object reference, a value type or string, a list, or a managed reference) rather than on the
declaring field's static type, so the same walk handles a captured scalar, a captured list, and a
captured element nested inside that list uniformly. A restored [SerializeReference] element comes
back as a fresh instance, so identity says nothing about it — its concrete type and every one of its own
serialized fields are what must match, which is why the managed-reference branch recurses field by field
instead of comparing the two instances directly. Previously duplicated byte-for-byte across
SerenityExistingAssetRestoreTests and several creators' own field-walk regression tests.
Inheritance
UnitySerializedFieldAssertions
Assembly: Tests.dll
Syntax
public static class UnitySerializedFieldAssertions
Methods
AssertRestored(string, object, object)
Asserts that actualValue matches expectedValue the way
a restore is expected to reproduce it: the same asset (or the same live object) for a Unity object
reference, equal value for a value type or string, element-by-element for a list, and field-by-field
for anything else (a managed reference, whose restored instance is never the same one captured).
Declaration
public static void AssertRestored(string fieldName, object expectedValue, object actualValue)
Parameters
DetachedCopyOf(object)
A copy that survives a later wholesale replacement of the SAME list or array a field holds —
a caller cannot rely on a captured collection staying untouched, and comparing the live collection
held as "the original" against itself after replacement would trivially pass regardless of what a
restore actually put back. Only a shallow copy: it protects the list's own identity, not a captured
element from being mutated in place afterward, so it fits a creator whose field application always
replaces the collection wholesale rather than editing an element of it in place.
Declaration
public static object DetachedCopyOf(object value)
Parameters
| Type |
Name |
Description |
| object |
value |
|
Returns
RestoredReferenceMatches(object, object)
Whether a restored Unity object reference points at the same THING the capture held, which for a
saved asset is not the same question as the same managed instance. A UnityEngine.Object is a
managed wrapper over a native object and Unity guarantees no single wrapper per object — which is
exactly why its own == compares instance ids rather than references. A reference re-marshalled
by EditorJsonUtility.FromJsonOverwrite, or an asset re-imported by the
AssetDatabase.Refresh() every rollback ends with, can therefore arrive as a second wrapper
over an asset that never moved; Assert.AreSame read that as a broken restore and failed
LocalizationLanguageCreatorTests' field walk in CI on a Texture2D alternate inside the
UnityEngine.Object[] that overwrite rebuilds.
So a saved asset is matched on what identifies the ASSET — its path, its GUID and its local file id
— which still tells a sub-asset from the main asset of the same file, and still tells two assets
apart however their names read. Anything that is not a saved asset (a scene object, an in-memory
instance, a target destroyed since the capture) has no asset identity, so it keeps reference
semantics. Public so UnitySerializedFieldAssertionsTests can pin the rule from both sides
without having to provoke assertion failures.
Declaration
public static bool RestoredReferenceMatches(object expectedValue, object actualValue)
Parameters
| Type |
Name |
Description |
| object |
expectedValue |
|
| object |
actualValue |
|
Returns