How to Embed Data with Unit Tests

The other day I caught Scott Hanselman's latest podcast on Mock Objects. It was pretty good as usual and while the topic that I am discussing here has little to do with Mock Objects, his discussion and passion around TDD or Unit Testing in general, got me fired up to make my tests better. In doing so, I solved a problem that I would imagine isn't all that unique to just me and the type of stuff I am testing.

I am writing a class library that is composed of a large set of classes that represent a data structure that requires XmlSerialization as well as a Stream that processes bytes converting the input into the stream to a different format of the data as output bytes.

Without getting into the details of the solution I am testing, I want to focus on an issue that arose early on in writing tests. Instead of mocking up interfaces to supply certain data to test, I just need to validate results against specific data (e.g. Is the XML that is produced from Serializing this object valid? Given certain XML representation of an object, can it deserialize back to a known object state? Will the processing of this binary data result in the expected output bytes?).

I had begun just creating large byte[] members or for the XML data just large strings, but that quickly became unwieldy. The solution is rather simple and I almost feel dumb for not thinking of this route sooner -- just put the data in files and embed them into the UnitTest project's build:

Once that is done, all you need to do to access the data is leverage the GetManifestResourceStream() method using Reflection:

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
Stream unmanagedStream = assembly.GetManifestResourceStream(resourceName);

The variable passed to the GetManifestResourceStream is the fully qualified name of the file you've embedded. For example, if the file was named Definition.xml was in a folder called SerializedObjects under the root of your project and your project's default namespace was _Company.Project, _you would set resourceName to "Company.Project.SerializedObjects.Definition.xml".

This will yield an Stream object that uses unmanaged memory. You can use this Stream object to get the data in whatever form makes sense to then use in your tests. I created a simple class with static methods to get the different types of data (XML strings and byte[]'s) that I need to test against.

Tags: tdd, unit testing, embed data, testing, software, development, vs 2005, visual studio