views:

307

answers:

2

I have a Singleton that is accessed in my class via a static property like this:OtherClassNotBeingTested.Instance.SomeInstanceMethod()

I would like to test my class with out making one of these objects. Is there a way for RhinoMocks to return a stub when the getter for the static property Instance is called?

To be clearer, here is the code for the Instance property:

    /// <summary>
    /// Make a property to allow the OtherClassNotBeingTested class 
    ///   to be a singleton 
    /// </summary>
    public static OtherClassNotBeingTested Instance
    {
        get
        {
            // Check that the instance is null
            //  NOTE: COMMENTS BELOW HAVE SHOWN THIS TO BE BAD CODE.  DO NOT COPY
            if (mInstance == null)
            {
                // Lock the object
                lock (mSyncRoot)
                {
                    // Check to make sure its null
                    if (mInstance == null)
                    {
                        mInstance = new OtherClassNotBeingTested();
                    }
                }
            }

            // Return the non-null instance of Singleton
            return mInstance;
        }
    }


Update: This is how I ended up fixing it:

class ClassBeingTested
{
    public ClassBeingTested(IGuiInterface iGui):this(iGui, Control.Instance)
    {

    }

    public ClassBeingTested(IGuiInterface iGui, IControl control)
    {
        mControl = control;

        //Real Constructor here
    }
}

My unit tests call the second constructor. The actual code calls the first constructor. The code in the class uses the local field mControl instead of the singleton. (I think this is called dependency injection.)

I also refactored the Singleton as per Tony the Pony's suggestion.

+4  A: 

I hope your mInstance variable is declared as volatile, otherwise your DCL implementation is broken. Seriously, do you really need that level of laziness? I'd personally recommend some of the simpler patterns available.

However, when it comes to mocking - no, you can't mock out static calls with RhinoMocks. There are some tools available which allow this, such as Typemock, but personally I'd refactor the app to be more testable in the first place.

Another option is to have a "cheating" singleton where you can set the value of the singleton property in your test case. If you make the property return an interface instead of the singleton class itself, you can replace the real singleton with a mock.

Jon Skeet
This construct is copy and pasted. I am going to change it to follow the pattern in your link. I think I am going to have a variable in the class that the singleton will assign to. That way I can mock that.
Vaccano
I, for one, welcome our Pony Overlord.
Jed Smith
+2  A: 

Tony the Pony's answer is correct. I'd like to add that testability problems are one of the reasons that the Singleton pattern has fallen out of favor. You may want to consider a DI/IoC (Dependency Injection/Inversion of Control) container framework such as Unity or StructureMap - these can create Plain Old Objects with Singleton-like lifespans.

TrueWill
That's Jon Skeet btw.....
RCIX