0

I am using the protobuf-net library for serialization/deserialization of messages.

Due to the distributed nature of the application some applications will have an older version of the object that is being used to serialize messages. The cases I'm concerned with are

  • adding new fields to the message object that some consumers(deserializers) won't have

  • removing fields in the message object that some consumers(deserializers) will still have.

Example an old app has this definition of Foo

class Foo
{
   public int Field1 {get; set;}
}

A newer app has this definition of Foo

class Foo
{
   public int Field1 {get; set;}
   public int Field2 {get; set;}
}

I want to have a test to verify that the library can deserialize an object with missing fields and fields that it isn't aware of in case I ever need to change my serialization library.

Is there an easy way to unit test this? C# won't let the user change the fields availabe in an object.

Currently I have to build my reciever app and then change the object that is transported to add a new field and then build my sending app to test this.

Is there a better way?

6
  • What kind of information do you want to obtain from the test? Which fields have been added or removed (a "diff")? Whether two serializations are functionally equal? You haven't made that clear in you're question; all you've said is "verify how the library works." What does "how the library works" mean? Jan 19, 2016 at 15:41
  • You'll have to make sure to keep track of version you're using and then drop/add the fields as necessary. There's not much you can do except keeping up with the API changes that may or may not break things. It's very difficult.
    – user7433
    Jan 19, 2016 at 15:44
  • @RobertHarvey I thought it was clear that I want to ensure that deserialization still works event though its missing a field or it has an extra field. I'll try to reword the question.
    – chollida
    Jan 19, 2016 at 15:49
  • 1
    Make two objects, remove a field from one object, serialize the first object, deserialize it to the second object, observe the results. (???) I guess I should have asked "What do you mean by 'better'?" Jan 19, 2016 at 15:51
  • 1
    You don't need dynamic objects to make this test work. You just need two ordinary classes. (????) In fact, you have two such classes in your question. Jan 19, 2016 at 15:55

3 Answers 3

9

Your deserialization test should take a String as its input, and try to produce a present-day object from it. Therefore, all you have to do is revert a copy of your project to an earlier state, save a serialized String, return to the head, and put that string into your test data. Unless I misunderstand your question, you never need to have different versions of the same class actually compiled in your code base.

1
  • @Killian That sounds like a promising approach. I could serialize objects with additional fields and missing fields to test how the deserializing works with the different serialized form.
    – chollida
    Jan 19, 2016 at 15:51
2

Maybe a little bit late, but I will answer for those who came across this question from search. I suggest using FluentAssertions library that provides an easy way of testing whether an object is serializable using one of the common serializations: Xml, Binary and DataContract:

using FluentAssertions;

theObject.Should().BeXmlSerializable();
theObject.Should().BeBinarySerializable();
theObject.Should().BeDataContractSerializable();

theObject.Should().BeBinarySerializable<MyClass>(
    options => options.Excluding(s => s.SomeNonSerializableProperty));
0

Every time you change the dataformat save an item with a standartized content to a dataformat-regression-folder together with a human-readable-version (i.e. xml) as expected result.

so you have file pairs of version-1.0.dat and version-1.0.dat.xml

Then write a regression-test that loops over all files in dataformat-regression-folder.

Pseudocode looks like this:

 foreach(String samplePath in LoadSamplePaths("dataformat-regression-folder\\*.dat"))
 {
     MyDataFormat sample = LoadSample(samplePath);
     MyDataFormat expected = LoadFromXml(samplePath + ".xml");
    assertEqual(sample.toXml(), expected.toXml());
 }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.