Skip to content

_Testing.Commons.Serialization

Daniel Gonzalez Garcia edited this page Aug 10, 2023 · 7 revisions
NOTE:
Serialization / deserialization support for binary, Json Contract, Json flavors have been **DEPRECATED in 3.0** and dropped in the netstandard version of the library.

If Json contract serialization features are needed, the most straightforward way would be adding the Nuget dependencies to your testing project and copy the code from the repository. But you are probably better off taking a dependency on a much better Json library.

Converting an object's state into a form that can be persisted can be achieved in quite a few ways, both included in the .NET Framework or provided by third party libraries.

Once serialization is contemplated as a feature, the mechanics to check whether a type is serializable and that the state is successfully saved and restored are pretty much independent of the actual details on how serialization/de-serialization is implemented.

The most commons scenarios, from the testing point of view are

  • check that the type can be successfully serialized and de-serialized
  • check that the serialized form of an object contains the same values as the original
  • provide examples of the serialization format

An abstraction for a round-trip

The first two of the supported scenarios are coded in the IRoundtripSerializer that representes a generic way of serializing an object for its later serialization.

Implementation of such interface are included for common serialization methods included in the .NET Framework: BinaryRoundtripSerializer, XmlRoundtripSerializer, DataContractRoundtripSerializer, DataContractJsonRoundtripSerializer, JsonRoundtripSerializer.

The basic usage is very simple and uses the IDisposable pattern as a way of cleaning the unmanaged resources used during the serialization/de-serialization cycle:

using (var subject = new BinaryRoundtripSerializer<Serializable>())
{
    var serialized = new Serializable { S = "s", D = 3m };
    subject.Serialize(serialized);

    Serializable deserialized = subject.Deserialize();

    Assert.That(deserialized, Is.Not.SameAs(serialized)
        .And.Property("S").EqualTo("s")
        .And.Property("D").EqualTo(3m));
}

An abstraction for deserialization

The last of the supported scenarios is coded in the IDeserializer that representes a generic way of transforming a string serialization representation into an object.

Implementation of such interface are included for common serialization methods included in the .NET Framework: XmlDeserializer, DataContractDeserializer, DataContractJsonDeserializer, JsonDeserializer.

An implementation for binary serialization is not included as it offers no value to provide a string representing the binary serialization format.

var subject = new XmlDeserializer();
var deserialized = subject.Deserialize<Serializable>(Serializable.XmlString("s", 3m));

Assert.That(deserialized.D, Is.EqualTo(3m));
Assert.That(deserialized.S, Is.EqualTo("s"));

Compact JSON

Sometimes, in our tests, we need to write JSON strings, such as {"prop": "value"}. Unfortunately for us C# developers, the double quote needs to be escaped in order for the string to be a valid C# string. That creates a lot of noise in our tests.

Wouldn't it be nice not having to escape all those quotes?

Compact JSON notation uses single quotes (perfectly embeddable in C# strings without escaping) so instead of writing "{\"property\"=\"value\"}" we can write "{'property'='value'}".

Expanding compact JSON

Instantiating JsonString

Compact JSON can be expanded by creating and instance of JsonString and than using it whenever the non-compact JSON is to be used. Such instances are implicitly convertible to strings.

var json = new JsonString("{'str' : 'value', 'number': 42}");

// use as a string
string nonCompact = json;

Extending the compact JSON

Compact JSON can be expanded by calling the .Jsonify() extension method on the compact representation. The extension tends to be a little bit more performant as less objects are allocated in the process.

string json = "{'str' : 'value', 'number': 42}".Jsonify();
Clone this wiki locally