Thursday, April 1, 2010

What Did Adding a .Moles File To My Project Do?

Obviously, adding a .moles file to your project added moles and stubs of the types in the targeted assembly. However, sometimes it can be a little difficult to figure out why certain classes got generated, where they are, and exactly what you’re supposed to do with them.

For starters, all moles and stubs end up in namespaces that are the same as the namespaces of the originating types with a “.Moles” slapped on the end. Types in “MyProject.MyClasses” have moles and stubs in “MyProject.MyClasses.Moles.”

IntelliSense your way into those namespaces and you’ll see a bunch of classes starting with “M” and “S.” I’ll let you guess what those stand for.

The basic rules for generating moles and stubs look like this:

1. Interfaces only get stubs generated for them.

2. Classes that can be derived from and instantiated get stubs generated for them, although if they have no abstract or virtual methods, you are limited in what you can do with it. This does not necessarily prevent them from having moles generated for them too, if they meet the criteria.

3. Pretty much everything except interfaces get moles generated for them. This includes, but isn’t limited to, things that can’t normally be extended/derived, such as classes without public constructors, sealed classes, static classes, classes with only non-virtual and/or non-abstract methods get moles generated for them. This does not prevent them from having stubs generated for them too, if they meet the criteria.

There are more rules that get into more complex stuff, but this should server you for 97% of everything, especially when you ask (as I often did at first), “why did this class get a mole but not a stub?”

The reason that these rules exist is because stubs follow the standard CLR rules – they can only override some piece of functionality by actually overriding it via inheritance or interface implementation. For this reason, they don’t require the [HostType(“Moles”] attribute on tests that use them. If you look at generated stub types, they derive from/implement the stubbed class/interface. Moles, on the other hand, throw CLR rules out the window. They rewrite the IL at runtime, so they can do pretty much anything.

If moles don’t inherit or derive from a class, how can mole instances be substituted for a class at compile time? Moles actually derive from a MoleBase in the Moles framework and are given an implicit conversion to the moled type. Moles of static methods don’t have to do this – they just derive from MoleBase, and the Moles host intercepts calls to the static method at runtime and reroutes them (the technical term is “detour”) to the mole implementation.

No comments: