犀牛嘲笑与单身人士

时间:2009-06-02 01:27:13

标签: .net singleton rhino-mocks

我正在使用来自第三方的组件。该组件为我们的应用程序中的上下文提供单例模式。我正在使用这个单身人士,但我想模仿这个对象进行测试。有没有办法在这个对象上完成模拟。

此外,构造函数被声明为private。

2 个答案:

答案 0 :(得分:2)

使用RhinoMocks,您必须拥有一个界面。如果你真的需要模拟这个,那么你将不得不通过将单例包装在另一个实例化接口的类中来作弊。该界面基本上需要是第三方单身人士类型的所有公共成员的副本。

这个概念类似于Duck Typing,但由于CLR不支持Duck Typing,你必须使用代理类。

以下是一个例子:

public interface ISingleton
{
    void SomePublicMethod();
    Int32 SomePublicProperty{ get; set; }
}

public class SingletonProxy: ISingleton
{
    private ThirdPartySingleton _singleton = StaticType.GetSingleton(); // ???

    public void SomePublicMethod()
    {
        _singleton.SomePublicMethod();
    }

    public Int32 SomePublicProperty
    {
        get{ return _singleton.SomePublicProperty; }
        set{ _singleton.SomePublicProperty = value; }
    }
}

所以现在无论你使用的是什么类型,都可以将其作为服务依赖项传递,如下所示:

public class TypeThatUsesSingleton
{
    private ISingleton _singleton;    

    public TypeThatUsesSingleton([HopefullySomeDependencyInjectionAttributeHere] ISingleton singleton)
    {
        _singleton = singleton;
    }

    public void DoStuff()
    {
        _singleton.SomePublicMethod();
    }
}

现在你应该能够愉快地模拟你的测试中的类并将其作为依赖项传递,以便让你的单元测试顺利进行:

[Test]
public void ShouldAssertSomeBehavior()
{
    var repo = new MockRepository();
    var singleton = repo.DynamicMock<ISingleton>();

    var sut = new TypeThatUsesSingleton(singleton);

    using(repo.Record())
    {
        singleton.SomePublicMethod();
    }
    using(repo.Playback())
    {
        sut.DoStuff();
    }
}

瞧!高兴地嘲笑单身人士没有头痛(好吧,所以有点头疼)。您可能认为整个Proxy类将会成为一个痛苦的屁股,但幸运的是,一些优秀的人已经让这更容易了。我之前提到的整个Duck Typing的东西......有一个开源库,可以在运行时为你生成代理类。

Duck Typing .Net

答案 1 :(得分:0)

如果第三方Singleton返回一个接口而不是一个具体类(它应该),那么Rhino模拟将能够模拟它。

如果您只想将其删除,请查看Rhino mocks'MockRepository.Stub<IMyInterface>()