Unit testing interceptors configuration

Jun 20, 2013 at 8:39 PM
Hi!
I'm going to make unit test to check unity configuration xml for each type, that have some attribute, correctly configured.

Is that possible to get from UnityContainer instance after LoadConfiguration call, for instance, what types are in interceptor section with InterfaceInterceptor type?

IUnityContainer container = IoCHelper.GetIUnityContainer();
container.LoadConfiguration();
....

Or only way is load app.config xml and parse it?
Jun 20, 2013 at 9:43 PM
Edited Jun 20, 2013 at 9:44 PM
habi2al,

At least you can always use UnityContainer.Registrations property (since Unity 3.0) to programmatically inspect loaded configuration.
Jun 20, 2013 at 9:46 PM
can You type an example, please.
Yeah, while debugging i'd got this list, but what ContainerRegistration are for <interceptor type="InterfaceIntercaptor">...</intercaptor>?
Jun 20, 2013 at 10:14 PM
Edited Jun 20, 2013 at 10:15 PM
Yep, my bad, you can't access Policy list via ContainerRegistration class.

But you have another option to look at. If you write your own container extension, it seems that you can get access to the policy list via ExtensionContext.Policies property. Once you have that, you can use that object to obtain whatever policy you want let alone the interception policy.

I can agree, it's not the most straightforward path, but still...

Hope this will help
Jun 21, 2013 at 5:59 AM
Yes, you can retrieve configuration information programmatically. For example:
var config = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
bool isInterceptionAttributeSetOnFirstRegistration = 
    config.Containers[0].Registrations[0].InjectionMembers[0].GetType() == 
        typeof(Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptorElement)
Your idea seems similar to what is done in some internal Unity test cases so looking at the source might be interesting to you. However, that just inspects the configuration and doesn't verify any code based attributes or perhaps verifying that some methods are intercepted while others are not.

Another approach might be to mock the interceptor and check to see if it executed. I'm not 100% sure how your code is designed but maybe something like this could be useful.

Let's say there is a config like this:
    <container>  
      <extension type="Interception" />
      <register type="ICallHandler" mapTo="MyCallHandler" name="MyCallHandler">
        <lifetime type="singleton"/>
      </register>
      <register type="ISubscriberRepository" mapTo="SubscriberRepository">
        <interceptor type="InterfaceInterceptor"/>
        <policyInjection />
      </register>
    </container>

So we have an interface mapped to an implementation and a call handler registered as a singleton. You could create and configure a mock call handler in the config or if you wanted to test (in a sense verify) the existing config you could programmatically override the config call handler with a mock.

Then there is the repository code which contains a custom call handler attribute:
    public class SubscriberRepository : ISubscriberRepository
    {
        [MyHandler]
        public void Add(string name)
        {
        }
    }

    public class MyHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return container.Resolve<ICallHandler>(typeof(MyCallHandler).Name);
        }
    }

The HandlerAttribute resolves the ICallHandler by name from the container. This can allow us to swap out the MyCallHandler implementation with a MockCallHandler:
    public class MockCallHandler : ICallHandler
    {
        // Get Input parameter back for verification
        public IMethodInvocation Input
        {
            get;
            private set;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            this.Input = input;
            return getNext()(input, getNext);
        }

        public int Order { get; set; }
    }

    IUnityContainer container = new UnityContainer().LoadConfiguration();

    // Get registration from config
    var myCallHandlerRegistration = container.Registrations
        .Where(r => r.RegisteredType == typeof(ICallHandler) &&
                    r.MappedToType == typeof(MyCallHandler))
        .First();

    // Create new LifetimeManager for this registration since we can't reuse it
    ConstructorInfo constructor = myCallHandlerRegistration.LifetimeManager.GetType().GetConstructor(new Type[0]);
    LifetimeManager lifetimeManager = (LifetimeManager)constructor.Invoke(new object[0]);

    // "overwrite" existing registration with mock
    container.RegisterInstance<ICallHandler>(myCallHandlerRegistration.Name, 
        new MockCallHandler(), 
        lifetimeManager);

    ISubscriberRepository repository = container.Resolve<ISubscriberRepository>();
    repository.Add("value1");

    // verify interception ran
    Debug.Assert("value1" ==
        ((MockCallHandler)container.Resolve<ICallHandler>(myCallHandlerRegistration.Name)).Input.Inputs[0]);

Also, as mentioned, container extensions let you do almost anything at the expense of complexity.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to