Rediscovering the Obvious

…stumbling in the footsteps of greatness

Archive for October, 2007

DelegatingMatcher

without comments

Really easy thing that I thought would be in the nMock framework somewhere, but couldn’t find: A way to call custom validation code against the matched object. With .NET2′s anonymous delegates, it was pretty easy to whip up just such a beast (with a bonus matcher thrown in for good measure):

    internal delegate bool ObjectMatcher(object o);

    internal class DelegatingMatcher : Matcher
    {

        public DelegatingMatcher( ObjectMatcher matcher )
        {
            _matcher = matcher;
        }

        private ObjectMatcher _matcher;

        public override void DescribeTo(System.IO.TextWriter writer)
        {
            writer.Write(“[DELEGATED]“);
        }

        public override bool Matches(object o)
        {
            return _matcher(o);
        }

        internal static bool NonZeroStringLengthMatcher(object o)
        {
            Assert.IsAssignableFrom(typeof(string), “Expected a string”);
            Assert.IsFalse(string.IsNullOrEmpty((string) o), “Expected contents in the string” );
            return true;
        }
    }
 

 

Usage:

            DelegatingMatcher thingMatcher = new DelegatingMatcher(new ObjectMatcher(
                delegate(object target)
                {
                    thingEntity thing= (thingEntity) target;
                    Assert.AreEqual(thingId, thing.ThingId);
                    Assert.AreEqual(newTitle, thing.Title);
                    Assert.AreEqual(contextId, thing.ContextId);
                    return true;
                }));
 

And

                 Expect.Once
                    .On(mockThingService)
                    .Method(“UpdateThing”)
                    .With(thingMatcher, new EqualMatcher(contextalValue), new EqualMatcher(false));

Written by erwilleke

October 25th, 2007 at 2:01 pm

Posted in Uncategorized

Testing delegates with nUnit and nMock

without comments

Recently, I’ve been trying to put real unit tests around the Presenters in our MVP pattern, and because the view fires events to notify the Presenter of behavior from the user, I’ve had a need to inject the proper subscription and firing of those events into nMock (2). A huge goal of nMock is to avoid creating mock objects as explicit implementations of interfaces, so I didn’t want to just give in and create full implementations for each view interface. The biggest miss, though, was confirming that the events had been properly subscribed to (as an expected condition) and then driving behavior into to component under test by firing that event with specific parameter values.

Being a good developer, I went searching (I won’t say Googling, since some MS evangelists might be reading my blog, and recently gave me a dirty look for saying it during his presentation), and this was the closest I could find:
http://becomingagile.blogspot.com/2007/03/raising-events-in-nmock-20.html

It worked great… almost. It relied on the delegate being derived from System.EventHandler, and it only passed “null, null” for sender and args. Not good enough, but a HUGE step in the right direction. So, planning on expanding his code, I realized that the single “unknowable” was HOW exactly to call the delegate. Everything else could be handled by making the delegate type into a generic. Luckily, we have a new language mechanism for extracting those little bits of unknowable calls, so I figured an anonymous delegate could probably get me where I wanted to go. So here’s what I did: (Full code at the bottom)

  1. Introduced a generic type parameter to both MockEvent<T> and MockEventHookup<T>, which represents the type of the delegate to be called.
  2. Introduced a generic delegate called void EventActivator<T>( T handler ), allowing the caller to specify the code to be executed to fire the event.
  3. Replaced all references to EventHandler with instances of T, and replaced the call to the event handler (In Raise) with a call to the EventActiviator I declared above

On the caller side, we end up with a new notation, but it pretty clearly expresses the intent… the ()’s next to handler would take any custom parameters for the delegate, and they would even be provided in the test’s context.

             // Configure the view’s mock
            MockEvent<EmptyEventHandlerDelegate> loadEvent
                = new MockEvent<EmptyEventHandlerDelegate>(
                    delegate(EmptyEventHandlerDelegate handler)
                    {
                        handler();
                    });

Then:

             Expect.Once
                 .On(view)
                 .EventAdd(“OnLoadView”, Is.Anything)
                 .Will(MockEvent < EmptyEventHandlerDelegate>.Hookup(loadEvent));
 And:

            loadEvent.Raise();

Here’s the full code for the evolved mock event.

using System;
using System.Collections.Generic;
using System.Text;
using NMock2;
using NMock2.Monitoring;
using System.IO;

namespace Presentation.Tests.HelperObjects
{
    /// <summary>
    /// Code by Eric Willeke — Keep my name here, please :)
    /// http://manicprogrammer.com/cs/blogs/willeke/archive/2007/10/17/testing-delegates-with-nunit-and-nmock.aspx
    /// Adapted from original code by Neil Bourgeois – Edmonton, Alberta, Canada
    /// http://becomingagile.blogspot.com/2007/03/raising-events-in-nmock-20.html
    /// </summary>
    public class MockEvent<T>
        where T : class
    {
        private T handler;
        EventActivator<T> activatingDelegate;

        public MockEvent(EventActivator<T> activatingDelegate)
        {
            if ( activatingDelegate == null )
                throw new ArgumentNullException();

            this.activatingDelegate = activatingDelegate;
        }

        public void Initialize(T handler)
        {
            if ( handler == null )
            {
                throw new ArgumentNullException();
            }

            this.handler = handler;
        }

        public void Raise()
        {
            activatingDelegate(handler);
        }

        public static IAction Hookup(MockEvent<T> mockEvent)
        {
            return new MockEventHookup<T>(mockEvent);
        }
    }

    public delegate void EventActivator<T>(T handler);

    public class MockEventHookup<T>
        : IAction
        where T : class
    {
        private readonly MockEvent<T> mockEvent;

        public MockEventHookup(MockEvent<T> mockEvent)
        {
            this.mockEvent = mockEvent;
        }

        public void Invoke(Invocation invocation)
        {
            T handler = invocation.Parameters[0] as T;

            if ( handler == null )
            {
                throw new Exception(
                    string.Format(
                        “Unknown event handler type. {0} was expected.”,
                        typeof(T).ToString()));
            }

            mockEvent.Initialize(handler);
        }

        public void DescribeTo(TextWriter writer)
        {
            // do nothing
        }

    }
}

Written by erwilleke

October 17th, 2007 at 9:54 am

Posted in Uncategorized

Dirty, or elegant?

without comments

The nature of our development standards require a certain degree of exception wrapping at every public layer boundary, and I’ve been getting frustrated with the need to write 11 extra lines of code for what could/should be a one line method. At the same time, I respect the reasons that led us to this approach. As such, I decided to find a way to make it as clean as possible. I arrived at the following approach using anonymous delegates to introduce an aspect (little a, not big AOP a)  to the class.

I’d like a consensus on whether this was scary, dirty, nasty shortcutting in code, or if it’s an elegant way to clean the code and encapsulate the default exception behavior for a layer.

First, the delegate side:

        private delegate void CodeDelegate();

        private void WrapBusinessExceptions(CodeDelegate code)
        {
            try
            {
                code();
            }
            catch ( BusinessException be )
            {
                throw;
            }
            catch ( Exception ex )
            {
                throw new BusinessException(ex);
            }
        }

 
Second, an example of the usage:

        public void ActivateUser(Guid userId)
        {
            WrapBusinessExceptions(delegate()
            {
                SetActivationStatus(userId, true);
            });
        }

[EDIT]

Turns out, there’s a problem there… no support for return values… to support any and all return types, I added this second, generics-based set of code (with corresponding example)

        private delegate T CodeDelegate<T>();

        private T WrapBusinessExceptions<T>( CodeDelegate<T> code)
        {
            try
            {
                return code();
            }
            catch ( BusinessException )
            {
                throw;
            }
            catch ( Exception ex )
            {
                throw new BusinessException(ex);
            }
        }

         public bool IsEmailAvailable(string email)
        {
            return WrapBusinessExceptions<bool>(delegate()
            {
                    return IsEmailUnique(email );
            });
        }

Written by erwilleke

October 10th, 2007 at 11:19 am

Posted in Uncategorized

So very busy… or some such

without comments

Well, I came here to complain how busy I’ve been and how it’s keeping me from writing… then I realized that I’ve been away long enough that my own blog doesn’t even show up in my browser’s autocomplete history… NO EXCUSES!

The reality is that I’ve been a lot more head-down coding, evolving, learning new technologies, and all-around learning my new project’s environment inside-and-out. I’ve never really had the opportunity to REALLY dig into the depths of ASP.NET, and this is a good chance… it feels good, although I miss WPF.

In other news, I did win a full copy of Expression Suite at the last ArcReady event, so I’m ABLE to continue blending from time to time.

   
 

Written by erwilleke

October 8th, 2007 at 4:09 pm

Posted in Uncategorized