Is there any point Unit testing serialization?

后端 未结 13 920
慢半拍i
慢半拍i 2021-02-01 23:38

I have a class that serializes a set of objects (using XML serialization) that I want to unit test.

My problem is it feels like I will be testing the .NET implementation

相关标签:
13条回答
  • 2021-02-02 00:14

    Yes, as long as what needs to be tested is properly tested, through a bit of intervention.

    The fact that you're serializing and deserializing in the first place means that you're probably exchanging data with the "outside world" -- the world outside the .NET serialization domain. Therefore, your tests should have an aspect that's outside this domain. It is not OK to test the Writer using the Reader, and vice versa.

    It's not only about whether you would just end up testing the .NET serialization/deserialization; you have to test your interface with the outside world -- that you can output XML in the expected format and that you can properly consume XML in the anticipated format.

    You should have static XML data that can be used to compare against serialization output and to use as input data for deserialization.

    Assume you give the job of note taking and reading the notes back to the same guy:

    You - Bob, I want you to jot down the following: "small yellow duck."
    Bob - OK, got it.
    You - Now, read it back to me.
    Bob - "small yellow duck"
    

    Now, what have we tested here? Can Bob really write? Did Bob even write anything or did he memorize the words? Can Bob actually read? -- his own handwriting? What about another person's handwriting? We don't have answers to any of these questions.

    Now let's introduce Alice to the picture:

    You - Bob, I want you to jot down the following: "small yellow duck."
    Bob - OK, got it.
    You - Alice, can you please check what Bob wrote?
    Alice - OK, he's got it.
    You - Alice, can you please jot down a few words?
    Alice - Done.
    You - Bob, can you please read them?
    Bob - "red fox"
    Alice - Yup, that sounds right.
    

    We now know, with certainty, that Bob can write and read properly -- as long as we can completely trust Alice. Static XML data (ideally tested against a schema) should sufficiently be trustworthy.

    0 讨论(0)
  • 2021-02-02 00:18

    If you want to ensure that the serialization of your objects doesn't break, then by all means unit test. If you read the MSDN docs for the XMLSerializer class:

    The XmlSerializer cannot serialize or deserialize the following:

    Arrays of ArrayList
    Arrays of List<T>

    There is also a peculiar issue with enums declared as unsigned longs. Additionally, any objects marked as [Obsolete] do no get serialized from .Net 3.5 onwards.

    If you have a set of objects that are being serialized, testing the serialization may seem odd, but it only takes someone to edit the objects being serialized to include one of the unsupported conditions for the serialisation to break.

    In effect, you are not unit testing XML serialization, you are testing that your objects can be serialized. The same applies for deserialization.

    0 讨论(0)
  • 2021-02-02 00:19

    I have done this in some cases... not testing the serialisation as such, but using some 'known good' XML serializations and then loading them into my classes, and checking that all the properties (as applicable) have the expected values.

    This is not going to test anything for the first version... but if the classes ever evolve I know I will catch any breaking changes in the format.

    0 讨论(0)
  • 2021-02-02 00:20

    I would argue that it is essential to unit test serialization if it is vitally important that you can read data between versions. And you must test with "known good" data (i.e. it isn't sufficient to simply write data in the current version and then read it again).

    You mention that you don't have a schema... why not generate one? Either by hand (it isn't very hard), or with xsd.exe. Then you have something to use as a template, and you can verify this just using XmlReader. I'm doing a lot of work with xml serialization at the moment, and it is a lot easier to update the schema than it is to worry about whether I'm getting the data right.

    Even XmlSerializer can get complex; particularly if you involve subclasses ([XmlInclude]), custom serialization (IXmlSerializable), or non-default XmlSerializer construction (passing additional metadata at runtime to the ctor). Another possibility is creative use of [XmlIngore], [XmlAnyAttribute] or [XmlAnyElement]; for example you might support unexpected data for round-trip (only) in version X, but store it in a known property in version Y.


    With serialization in general:

    The reason is simple: you can break the data! How badly you do this depends on the serializer; for example, with BinaryFormatter (and I know the question is XmlSerializer), simply changing from:

    public string Name {get;set;}
    

    to

    private string name;
    public string Name {
        get {return name;}
        set {name = value; OnPropertyChanged("Name"); }
    }
    

    could be enough to break serialization, as the field name has changed (and BinaryFormatter loves fields).

    There are other occasions when you might accidentally rename the data (even in contract-based serializers such as XmlSerializer / DataContractSerializer). In such cases you can usually override the wire identifiers (for example [XmlAttribute("name")] etc), but it is important to check this!

    Ultimately, it comes down to: is it important that you can read old data? It usually is; so don't just ship it... prove that you can.

    0 讨论(0)
  • 2021-02-02 00:20

    There are a lot of types that serialization can not cope with etc. Also if you have your attributes wrong, it is common to get an exception when trying to read the xml back.

    I tend to create an example tree of the objects that can be serialized with at least one example of each class (and subclass). Then at a minimum serialize the object tree to a stringstream and then read it back from the stringstream.

    You will be amazed the number of time this catches a problem and save me having to wait for the application to start up to find the problem. This level of unit testing is more about speeding up development rather then increasing quality, so I would not do it for working serialization.

    As other people have said, if you need to be able to read back data saved by old versions of your software, you had better keep a set of example data files for each shipped version and have tests to confirm you can still read them. This is harder then it seems at first, as the meaning of fields on a object may change between versions, so just being able to create the current object from a old serialized file is not enough, you have to check that the meaning is the same as it was it the version of the software that saved the file. (Put a version attribute in your root object now!)

    0 讨论(0)
  • 2021-02-02 00:21

    If the format of the serialized XML matters, then you need to test the serialization. If it's important that you can deserialize it, then you need to test deserialization.

    0 讨论(0)
提交回复
热议问题