Testing and Debugging MEF, Tips - Part 1

this is the first post of a series that will offer some tips
about testing and debugging your MEF-able component and application.
in this post we will focus about exporting Mock objects.
the code sample for this post can be download from here.
Prerequisite
if you are not familiar with Mocks you better read more about this subject before
proceeding with this post (in short Mocks are fake object which is use for separate
dependencies during unit testing).
the sample is using the Moq library as it mocking infrastructure.
Having the following code:
1. contract
Contract
- public interface ILogger
- {
- void Write(string message);
- }
2.exported contract implementation
Export (contract implementor)
- [Export (typeof(ILogger))]
- public class DebugLogger: ILogger
- {
- public void Write(string message)
- {
- Debug.WriteLine(message);
- }
- }
line1: export the class as ILogger
3. contract consumer
Import (contract consumer)
- public class MyLogic
- {
- [ImportMany]
- private IEnumerable<ILogger> Loggers { get; set; }
-
- public void DoYourThings()
- {
- foreach (ILogger logger in Loggers)
- {
- logger.Write("Some log");
- }
-
- Console.WriteLine("Done");
- }
- }
line 3: import any available loggers
4. composition and execution
Main
- class Program
- {
- static void Main(string[] args)
- {
- var logic = new MyLogic();
- var cat = new AssemblyCatalog(typeof(Program).Assembly);
- var container = new CompositionContainer(cat);
- container.ComposeParts(logic);
-
- logic.DoYourThings();
- logic.DoYourThings();
-
- Console.ReadKey();
- }
- }
How can we write unit test for the DoYourThings method?
MEF dependencies is already loosely coupled by it nature, but in order to
validate the method behavior we still need to check whether the the method
do write logs.
we will inject a Mock<ILogger> into the MEF container in order to validate
this behavior.
the following code snippet is showing how:
Test
- [TestMethod]
- public void TestMethod1()
- {
- // Arrange
- var logic = new MyLogic();
- var container = new CompositionContainer();
- var loggerMock = new Mock<ILogger>();
- container.ComposeExportedValue<ILogger>(loggerMock.Object);
- container.ComposeParts(logic);
-
- // Test
- logic.DoYourThings();
-
- // Validate
- loggerMock.Verify(logger => logger.Write(It.IsAny<string>()), Times.Once());
- }
line 7: creating mock object.
line 8: inject the mock object into the container.
Summary
using the ComposeExportedValue method, we can inject
mock object into our CompositionContainer, therefore at the composition stage
the Import properties will get our mock objects.