var self = justin();

Software Developer Teammate

A place to remind my future self of what I've learned and experienced. That means both my successes and failures.


Capturing Parameters with Rhino Mock

The Setup

When writing tests, using a mock framework helps with isolating the exact code or functionality you want to test. I've been using RhinoMocks at my current client and like it. However, recently I had a situation where my class under test accepted input, made some modifications to it, then passed that modified input to a service. I mocked the service but I really wanted to make sure my logic around the input modification was correct.

Options

The way I saw it, I had three options:
1. I could refactor the logic around modifying the input into a separate class that could be tested independently.
2. I could have somehow capture the parameters being passed into the service and make assertions on that
3. I could skip that and try to test the logic via an intergration test later down the line.

Capturing the Parameters

Well, I chose option 2. RhinoMocks provides a way of stubbing out a method on a mock or a stub and then providing a different implementation for that method. So, with this and the power of Closures, I was able to hold onto the parameter that was passed to the service and inspect it.

Code

Here's how to do that:

using System;
using NUnit.Framework;
using Rhino.Mocks;

namespace RhinoMocksTest
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    public class InputModifier
    {
        private readonly IService service;

        public InputModifier(IService service)
        {
            this.service = service;
        }

        public void ModifyInput(string input)
        {
            //Modifying the input
            input = input.ToLower();
            service.Submit(input);
        }
    }

    public interface IService
    {
        void Submit(string input);
    }

    [TestFixture]
    public class TestInputModifier
    {
        private delegate void CaptureParameters(string input);

        [Test]
        public void InputShouldBeModifiedBeforeSendingToService()
        {
            //Arrange
            var input = "JUSTIN";
            var serviceStub = MockRepository.GenerateStub<IService>();

            //This is where the input will go.
            string capturedInput = null;

            //That parameter that is passed into the Submit method will be captured
            //via a closure into capturedInput
            Action<string> captureStringInput = data =>
            {
                capturedInput = data;
            };

            //When our class under test calls service.Submit(), rhino will use our delegate;
            serviceStub.Stub(service => service.Submit(Arg<string>.Is.Anything))
                .Do(new CaptureParameters(captureStringInput));

            var inputModifier = new InputModifier(serviceStub);

            //Act
            inputModifier.ModifyInput(input);

            //Assert
            Assert.That(input.ToLower() == capturedInput);
        }

    }
}
comments powered by Disqus