MEFUnit – Prototype of a MEF Unit Testing Framework

Recently I have been paying close attention to MEF, the Managed Extensibility Framework. MEF is an extremely powerful framework aimed at making parts (internal or external extensibility points) more discoverable.

While I was looking at this, it dawn on me. Unit testing frameworks main role is identifying and executing methods. If that is their main function – how could you use MEF to identify and execute those methods? The result of this pondering is MEFUnit. Like with xUnit.GWT this is located on GitHub and has been mentioned on twitter once or twice.

The Tests

The tests look very similar to any other kind of unit testing framework you might have used. The attribute [Mef] identifies which methods should be executed, and like with any other framework they can pass (no exception), fail (assertion exception) and be skipped (skipped exception).

Fundamentally, this is the main concept of most unit testing frameworks. Yes, some have parameterized tests and other such features which are great, but many people got by with just this. When you run the tests, you get the following output.

But how are these methods actually turned into unit tests? The main point in the above example is the MEF attribute. This is simply a custom ExportAttribute. I could have wrote:

[Export("Mef", typeof(Action)]public void Test() {}

However, I feel creating a custom attribute improves the readability and usability of my framework for the user. It also means if I need to change the contract I can do it without effecting my dependent exports. The second important fact is that the exports are of type Action. By storing the method references as Action I can executed them anywhere in my code. This is the trick which makes this all possible. It means I can execute each test as shown and report the result to the console.

The Mefs collection is populated via the MEF framework and the use of an Import attribute. Within the class, the property looks like this:

[MefTests]public IEnumerable Mefs { get; set; }

As with the Export attribute, I wanted to hide the actual contract I used to import the Action methods. This allowed me to hide the fact I was using AllowRecomposition, enabling tests to be dynamically identify when new assemblies are loaded.