简体   繁体   English

犀牛Mo-Stub a Singleton

[英]Rhino Mocks - Stub a Singleton

I have a Singleton that is accessed in my class via a static property like this: OtherClassNotBeingTested.Instance.SomeInstanceMethod() 我有一个Singleton,该类可以通过这样的静态属性在我的班级中访问: 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? 调用静态属性Instance的getter时,RhinoMocks是否可以返回存根?

To be clearer, here is the code for the Instance property: 为了更清楚,这是Instance属性的代码:

    /// <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. 类中的代码使用本地字段mControl而不是单例。 (I think this is called dependency injection.) (我认为这称为依赖注入。)

I also refactored the Singleton as per Tony the Pony 's suggestion. 根据Tony the Pony的建议,我还重构了Singleton。

I hope your mInstance variable is declared as volatile, otherwise your DCL implementation is broken. 我希望将您的mInstance变量声明为volatile,否则您的DCL实现被破坏了。 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. 但是,当涉及到模拟时-不,您不能使用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. 有一些可用的工具允许这样做,例如Typemock ,但我个人首先将应用程序重构为可测试性更高。

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. 如果使属性返回接口而不是单例类本身,则可以用模拟代替真正的单例。

Despite other rumors you can mock singletons, see my answer to: 尽管有其他谣言,您可以嘲笑单身人士,请参阅我的回答:

How to Mock a Static Singleton? 如何模拟静态单例?

In this case it's even simpler, because there is no static constructor. 在这种情况下,它甚至更简单,因为没有静态构造函数。 If your singleton implements an interface already, there'd be no need to change your productive code. 如果您的单例已经实现了接口,则无需更改生产代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM