NMock extensions and .NET 4. Avoiding “magical” and hardcoded strings in method names

When I’ve started using NMock in my new dotnetneural project I’ve faced with “magical” strings in stubs. Fortunately .NET 4 framework allows us to avoid them totally.

Basically we’re using NMock to create stubs for some interfaces. Let’s say we’ve got following interface:

    public interface ICalculator
    {
        int Sum(int a, int b);
        int GetLastResult();
    }

Now let’s create unit test (using NUnit framework) which will use stub of this interface:

    [TestFixture]
    public class TestCalculator
    {
        [SetUp]
        public void SetUp()
        {
            mockery = new Mockery();
        }

        [Test]
        public void SumTwoNumbers_NegativeNumbers_SumIsNegative()
        {
            calc = mockery.NewMock<ICalculator>();
            Stub.On(calc).Method("Sum").With(-1, -2).Will(Return.Value(-3));
            Stub.On(calc).Method("GetLastResult").WithNoArguments().Will(Return.Value(-3));

            int val = calc.Sum(-1, -2);
            Assert.AreEqual(-3, val);

            int lastVal = calc.GetLastResult();
            Assert.AreEqual(-3, lastVal);
        }

        private ICalculator calc;
        private Mockery mockery;
    }

As you can see we’re creating stub and setup two methods: Sum() and GetLastResult(). Then we simply check that stub works as expected. Everything is good except we’re using hardcoded method names during stub configuration.

Let me introduce extension methods for NMock which will allow us to avoid hardcoding method names:

    public static class NMockExtensions
    {
        public static IArgumentSyntax Method<TType, TResult>(this IMethodSyntax ms, Expression<Func<TType, TResult>> expr)
        {
            LambdaExpression le = expr as LambdaExpression;
            MethodCallExpression mc = le.Body as MethodCallExpression;

            var result = GetMethod(ms, mc);

            if ( result == null )
            {
                UnaryExpression ue = le.Body as UnaryExpression;
                if (ue != null)
                {
                    mc = ue.Operand as MethodCallExpression;
                    result = GetMethod(ms, mc);
                }
            }

            return result;
        }

        private static IArgumentSyntax GetMethod(IMethodSyntax ms, MethodCallExpression mexpr)
        {
            if (mexpr != null)
            {
                var mi = mexpr.Method;
                if (mi != null)
                {
                    return ms.Method(mi);
                }
            }

            return null;
        }
    }

Using this extension method out test can be rewritten:

    [TestFixture]
    public class TestCalculator
    {
        [SetUp]
        public void SetUp()
        {
            mockery = new Mockery();
        }

        [Test]
        public void SumTwoNumbers_NegativeNumbers_SumIsNegative()
        {
            calc = mockery.NewMock<ICalculator>();

            Stub.On(calc).Method<ICalculator, int>((c) => c.Sum(-1, -2)).Will(Return.Value(-3));
            Stub.On(calc).Method<ICalculator, int>((c) => c.GetLastResult()).Will(Return.Value(-3));

            int val = calc.Sum(-1, -2);
            Assert.AreEqual(-3, val);

            int lastVal = calc.GetLastResult();
            Assert.AreEqual(-3, lastVal);
        }

        private ICalculator calc;
        private Mockery mockery;
    }

As you can see now we aren’t hardcoding method names for our stubs. Intellisense is working as well as find usage and rename functionality:

Find usage of interface method in VS2010

Advertisement

2 Responses to “NMock extensions and .NET 4. Avoiding “magical” and hardcoded strings in method names”

  1. Keith Says:

    I really like NMock and have pushed it into our projects for quite some time. However, I’m a bit concerned that it maybe a ‘dead’ project as the last updated (i.e. 2.0 RC2) seems to have taken place two years ago. Instinctively this makes me want to look for an alternative. Any thoughts or suggestions?

    • tillias Says:

      Hi Keith!

      I suppose your unit-testing solutions based on NMock will never come to production and customers. If it satisfies all your current needes then you shouldn’t switch to another mocking framework.
      Small number of releases means of stability of product (remind FLAC open source codec releases). Popular ioc autofac uses NMock2 integration and these people know what they do.

      Anyways try to look at Rhino Mocks and Moq for alternative.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.