2011-06-17

Silverlight and Unit Testing - Reference Gotcha When Testing View Code

I'm new to Silverlight and am still learning my way around various nuances of the platform.

I like it so far and have been learning a lot. When a recent check-in was made by a co-worker to our project at work, we had around 90 of over 800 unit tests broken with this error in each of them:
The attachable property 'TransitionEffect' was not found in type 'ExtendedVisualStateManager'.

Being new to XAML, I had no idea where to start, except to go find the .xaml files resource dictionaries to try to figure out what the problem was.  Searching the internet made it sound like I had x:Name attributes with the same values from different dependent XAML files.

I should mention I was working in a UserControl XAML file to begin with, and started searching up the dependency hierarchy to see if the naming problem was the real issue.

The XAML files were quite large, so finding all the x:Name attributes and comparing them was going to take a while.  I opted to approach this using LINQPad.  I replaced quotes with double-quotes in the XAML so I could bring it into LINQPad as a string constant and loaded it into a XDocument object; using LINQ to XML to find matches from the other file's XAML for me.  After discovering one, I fixed it and re-ran my unit tests.  I still got the same error.

What I didn't understand was that the application ran fine and the effect was working... why on earth wouldn't it work in our unit tests?  It should have dawned on me that both the application project and the unit test project required the appropriate DLLs to be referenced in order for that namespace to be available.

Sure enough, the application project had them but the unit test project did not.  As soon as I added the references, the tests passed with flying colors again.

The required references, for those that get the exact same error:
Microsoft.Expression.Effects
Microsoft.Expression.Interactions
(both part of the Silverlight v4.0 Toolkit)

Moral of the story: When you add references to your application project, make sure you add them to the corresponding unit test project if necessary as well.

Now the next question... Why was I required to have those when I wasn't rendering any UI, but merely using the View classes in the unit test?  It seemed as if the XAML was still being parsed.

This makes sense, being as your View classes are declared as partial and the other piece to this partial puzzle is the XAML file.  Remember that whenever the View class is constructed, the InitializeComponent method is called, which parses the XAML and sets up everything declared there (correct me if I'm not describing that accurately!)

That said, if you're going to unit test a view file, you have to make sure that anything required by the XAML files are also referenced.  It's easy to take care of that for the C# files because you get compile-time errors, but you don't necessarily with the declarative XAML files.  A drawback, but one that can be handled if we're aware.

Bottom line... remember that both the XAML and corresponding C# file make up your View class and both files' reference requirements must be met to ensure all namespaces/code are available for your unit tests.

I hope this will save you (and myself) a lot of time in the future if I ever encounter this problem again.

No comments: