Subscribe To

About Me

I love using SpecsFor to write tests. However, there’s a function in the library called ShouldLookLikePartial that works on anonymous objects, that has always left a little to be desired. Recently I decided to fix it, and with the next release of SpecsFor, my change will be in! This involved me diving into some expression parsing, which was much easier than I thought it would be. I also thought it was pretty interesting, so I decided to share what I dug up. Read on if you’re interested!

The Problem

One common thing you do when testing is assert that your result (say a view model) looks like you expect. But lets say your result involves a new domain object being created and saved. You want to verify its properties are set correctly, but there’s probably some fields you don’t care about (like an ID).

Originally, you would use the ShouldLookLikePartial method in SpecsFor.

This accepts an anonymous object, so it only compares what you’ve defined. However, you’ve lost one of the big advantages of a statically typed language. Your tests are no longer refactor friendly. We want our feedback cycle to tell us ASAP when something is wrong. If you renamed a field, your code would still build. It wouldn’t fail until you ran your tests. With tools like ReSharper, renaming a field is typically very safe, but we’ve just made it a little more brittle.

The Solution

I worked with Matt Honeycutt (owner and creator of SpecsFor) to come up with the syntax we wanted - which is pretty much “works just like the old Partial version, except you declare your type now”. So that’s what I did!

The How

Well, the simplest way to see how is to check out the code, of course. I’m going to talk about some high level parts here, but suggest you take a look at the code to see it all working together in action. The meat of it is simply in checking the Body property of the expression. For a simple initializer, it’ll be MemberInitExpression.

varmemberInitExpression=matchFunc.BodyasMemberInitExpression;

From there, you can use the helper function off the Expression class to turn the expression into a lambda, compile it, and execute it. Then you have your expected value:

Now, since we don’t want to compare the entire value, only the specified properties, we can loop through the Bindings property of the MemberInitExpression. If this is another expression, we call ourselves with recursion. Otherwise, we use reflection and just test the values. Here’s the code snippet of us checking to see if we need to use recursion or not:

Put those bits all together, and we have a pretty simple class that makes our tests a lot easier to read and maintain. I really do recommend checking out the finished class if you want to see how it all gels together!

TL;DR

Don’t use ShouldLookLikePartial anymore. Use ShouldLookLike! You can now have your cake and eat it too!

If you find any bugs, please report them at the GitHub SpecsFor repository! Also please let us know if there’s some functionality that ShouldLookLikePartial used to perform that ShouldLookLike does not.