views:

385

answers:

5

I have number of classes I've been asked to add some unit tests to with Rhino Mocks and having some issues.

First off, I know RhinoMocks doesn't allow for the mocking of Static members. I'm looking for what options I have (besides using TypeMock).

An example of the class I have is similar to the below:

class Example1 : ISomeInterface
{
    private static ISomeInterface _instance;

    private Example1()
    {
        // set properties via private static methods
    }

    static Example1()
    {
        _instance = new Example1();
    }

    public static ISomeInterface Instance() 
    {
        get { return _instance; }
    }

    // Instance properties 

    // Other Instance Properties that represent objects that follow a similar pattern.
}

So when I call the above class, it looks something like this...

Example1.Instance.SomeObject.GoDownARabbitHole();

Is there a way for me to mock out the SomeObject.GoDownARabbitHole() in this situation or mock out the Instance?

+1  A: 

You can mock the interface, ISomeInterface. Then, refactor the code that uses it to use dependency injection to get the reference to the singleton object. I have come across this problem many times in our code and I like this solution the best.

for example:

public class UseTheSingleton
{
    private ISomeInterface myX;

    public UseTheSingleton(ISomeInterface x)
    {
        myX = x;
    }

    public void SomeMethod()
    {
        myX.
    }
}

Then ...

UseTheSingleton useIt = UseTheSingleton(Example1.Instance);
TheSean
+4  A: 

Singletons are at odds with Testability because they are so hard to change. You would be much better off using Dependency Injection to inject an ISomeInterface instance into your consuming classes:

public class MyClass
{
    private readonly ISomeInterface dependency;

    public MyClass(ISomeInterface dependency)
    {
        if(dependency == null)
        {
            throw new ArgumentNullException("dependency");
        }

        this.dependency = dependency;
    }

    // use this.dependency in other members
}

Notice how the Guard Claus together with the readonly keyword guarantees that the ISomeInterface instance will always be available.

This will allow you to use Rhino Mocks or another dynamic mock library to inject Test Doubles of ISomeInterface into the consuming classes.

Mark Seemann
+1  A: 

Here's a low-touch approach that uses a delegate, which can be set initially and changed at runtime. It's better explained by example (specifically, mocking DateTime.Now):

http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/11/09/systemtime-versus-isystemclock-dependencies-revisited.aspx

Peter Seale
Very interesting approach to the adapter pattern. Thanks
JamesEggers
+1  A: 

Check out Dependency Injection.

You've already began this, but for hard to test classes (statics etc...) you can use the adapter design pattern to write a wrapper around this hard to test code. Using the interface of this adapter, you can then test your code in isolation.

For any unit testing advice, and further testing issues check out the Google Testing Blog, specifically Misko's articles.

Instance

You say you are writing tests, so it may be too late, but could you refactor the static to the instance? Or is there a genuine reason why said class should remain a static?

Finglas
The example usage line I gave under the class definition is used in probably close to 100 or more files. I'm actually trying to test a class that calls this static singleton class which is simple if I could mock this away. So the workload to turn it into an instance class and not a static singleton would be risky sadly.
JamesEggers
That's fair enough. In that case, DI would be the way to go. Happy testing.
Finglas
A: 

You don't have to fix all the uses at once, just the one you're dealing with now. Add an ISomeInterface field to the class under test and set it through the constructor. If you're using Resharper (you are using Resharper, aren't you?), most of this will be trivial to do. If this is really fiddly, you can have more than one constructor, one which sets the new dependency field, the other which calls the first one with the singleton as a default value.

Steve Freeman