I want to refactor a DLL to make it MEFable too. Should I unit test whether a class is decorated with [Export] or [Import] and other MEF attributes?
A:
After thinking some hours and reading some TDD blogs again I should say, YES, I have to test whether my class has MEF attributes or not.
So before refactoring my classes I write unit tests in that way:
[TestClass]
public class When_SampleClass_mefable
{
[TestMethod]
[TestCategory("LFF.Kabu.Win.Login.ViewModel.SampleClass")]
public void Should_SampleClass_be_marked_with_Export_Attibute()
{
//arrange
var info = (typeof (SampleClass));
//act
var attr = info.GetCustomAttributes(true);
var hasExportAttribute =
attr.Where(x => x.GetType() == typeof (ExportAttribute))
.Where(x => ((ExportAttribute)x).ContractType == typeof(SampleClass))
.Count() > 0;
//assert
Assert.IsTrue(hasExportAttribute, "SampleClass is not marked with Export.");
}
}
For other MEF attributes like [ImportingConstructor] or [PartCreationPolicy] I do it the same way.
blindmeis
2010-08-12 08:14:36
+1
A:
Your tests should focus more on the goal instead of the mechanism. Create tests that verify things like "if I throw types X, Y and Z together in a container, then I can pull an IFoo interface from the container", like this:
[Test]
public void Can_get_IFoo_from_container_with_Foo_Bar_Baz()
{
var catalog = new TypeCatalog(typeof(Foo), typeof(Bar), typeof(Baz));
using (var container = new CompositionContainer(catalog))
{
var test = container.GetExportedValue<IFoo>();
}
}
This is no longer a real "unit" test because it involves multiple classes and an IoC container. We just call them "composition tests".
Wim Coenen
2010-08-12 10:53:50
well i think when i do unit test then i just want to know that my class(unit) behave like expected. i really dont want to test wether composing, and so wether MEF is working like expected. for my piece of code i just have to guarantee that the attributes are set. if at runtime composing did not satisfy my imports or exports, its not the problem of my class(unit). do you aggree with this?
blindmeis
2010-08-12 11:16:48
@blindmeis: I don't agree. MEF attributes are metadata which are only relevant for integration. You're trying to put integration concerns into a unit test, which doesn't fit. Imagine you change the contract type on all imports, but forget to change the export on the class under test. Your unit test will not detect this: it will continue to verify that the wrong export attribute is present. My test would detect the mismatch.
Wim Coenen
2010-08-12 12:41:59
you are right with your composition tests. but i see my unit test as that what it is a unit test. so if i change a contract, the unit where i do this change will fail and it should. but then i know thats right cause requirements changes and so i have to change my unit test too. i see your composition test necessary but on a higher level than unit test. btw i just did the test cause i try to learn the tdd way.and there i had the requirement that my class should be mefable.
blindmeis
2010-08-12 16:26:09
I agree with this, you don't test the implementation. You test that given the right inputs, the expected output occurs. In this case, the expected output is that when you generate a catalog, you plug in occurs.
Rich
2010-09-10 18:54:39