Showing posts with label design pattern. Show all posts
Showing posts with label design pattern. Show all posts

Thursday, 27 January 2011

Mocking dependencies

Given the following UtilityClassProvider and UtilityClass classes, what are suitable ways of mocking out the call to SomeUsefulMethod() and isolating the MethodUnderTest()? Wrinkle: UtilityClass needs to stay sealed.

public class UtilityClassProvider
{
    public T Get<T>() where T : new()
    {
        return new T();
    }
}

public sealed class UtilityClass
{
    public void SomeUsefulMethod()
    {
    }
}

public class ClassUnderTest
{
    public UtilityClassProvider UtilityClassProvider { get; set; }

    public void MethodUnderTest()
    {
        UtilityClassProvider.Get<UtilityClass>().SomeUsefulMethod();
    }
}

[TestFixture]
public class Tests
{
    // Fails; Rhino can't mock a sealed class
    [Test]
    public void Test()
    {
        var mockUtilityClass = MockRepository
            .GenerateMock<UtilityClass>();
        mockUtilityClass
            .Expect(o => o.SomeUsefulMethod());
        var mockUtilityClassProvider = MockRepository
            .GenerateMock<UtilityClassProvider>();
        mockUtilityClassProvider
            .Expect(o => o.Get<UtilityClass>())
            .Return(mockUtilityClass);

        var classUnderTest = new ClassUnderTest() { 
            UtilityClassProvider = mockUtilityClassProvider };
        classUnderTest.MethodUnderTest();

        mockUtilityClassProvider.VerifyAllExpectations();
        mockUtilityClass.VerifyAllExpectations();
    }
}

Unsealing UtilityClass would make mocking easier – but what are the alternatives?

Sunday, 3 October 2010

empty XmlNodeList and avoiding a null check

Now, why does XmlNode.SelectNodes(string xpath) return null if it doesn’t find anything?

I have some existing code that reads some parameters from XML, and passes some objects and those parameters into a method that filters those objects into two sets – one that is sensitive in some way to those parameters, and one that’s not.

FilterProducts(
    XmlNodeList processes, 
    XmlNodeList processAttributes, 
    out List<Product> sensitiveFolio,
    out List<Product> nonSensitiveFolio);

I’m drawing the list of processes and processAttributes from XML – and in some cases people don’t define any attributes, wanting to just build a folio sensitive to a list of processes. In this case the XmlNodeList returned is null – and when I pass that to FilterProducts it blows up.

After the null pattern, then, I figured what I wanted to do was actually pass an empty XmlNodeList rather than a null. FilterProducts could then just pass over the attributes, and work out what was dependent on the processes only. Then I realised that what I really needed to do was dig through FilterProducts and refactor it because it was doing too much – at least compared to the usage pattern was now different to that which originally formed it.

However; both these can happen in sequence. I could deliver the simpler – using the existing code and an empty list, which wouldn’t affect any other code, then taking a look at refactoring FilterProducts, which might affect other parts of the codebase. So, populate processAttributes with a successully parsed XmlNodeList, or a new EmptyNodeList if that's null:

XmlNodeList processAttributes = 
    myConfigNode.SelectNodes("/processAttributes") ?? new EmptyNodeList; 

and then defined EmptyNodeList by subclassing XmlNodeList:

private class EmptyNodeList : XmlNodeList 
{ 
    public override XmlNode Item(int index) 
    {
        throw new NotImplementedException(); 
    }

    public override IEnumerator GetEnumerator() 
    { 
        return new EmptyNodeListEnumerator(); 
    }

    public class EmptyNodeListEnumerator : IEnumerator 
    { 
        public bool MoveNext() 
        { 
            return false; 
        }

        public void Reset() 
        { 
            throw new NotImplementedException(); 
        }

        public object Current 
        { 
            get 
            { 
                throw new NotImplementedException(); 
            } 
        } 
    }

    public override int Count 
    { 
        get 
        { 
            return 0; 
        } 
    }     
}

That works fine, delivering some code, and leaving a look at refactoring some code used in multiple places for later.