注入犀牛模拟“假”工厂

时间:2011-06-08 19:45:56

标签: c# dependency-injection rhino-mocks factory-pattern

我正在尝试测试一个动态实例化对象并将它们存储在集合中的类。因为我需要测试实例化它们的逻辑以及对这些对象的操作,所以我认为创建一个可以注入进行测试的辅助假工厂类是个好主意。这是我想出来的

public class RhinoFakeFactory<TFakeable> where TFakeable : class
{
    public List<TFakeable> Fakes { get; set; }
    public FakeType FakeTypeToCreate { get; set; }

    public TFakeable GetFake()
    {
        TFakeable fake = default(TFakeable);

        switch (FakeTypeToCreate)
        {
            case FakeType.None:
            case FakeType.Stub:
                fake = MockRepository.GenerateStub<TFakeable>();
                break;
            case FakeType.DynamicMock:
                fake = MockRepository.GenerateMock<TFakeable>();
                break;
            case FakeType.DynamicMockWithRemoting:
                fake = MockRepository.GenerateDynamicMockWithRemoting<TFakeable>();
                break;
            case FakeType.StrickMock:
                fake = MockRepository.GenerateStrictMock<TFakeable>();
                break;
            case FakeType.StrickMockWithRemoting:
                fake = MockRepository.GenerateStrictMockWithRemoting<TFakeable>();
                break;
            case FakeType.PartialMock:
                fake = MockRepository.GeneratePartialMock<TFakeable>();
                break;
        }

        Fakes.Add(fake);
        return fake;
    }

    public RhinoFakeFactory()
    {
        Fakes = new List<TFakeable>();
    }
}

public enum FakeType
{
    None,
    Stub,
    DynamicMock,
    DynamicMockWithRemoting,
    StrickMock,
    StrickMockWithRemoting,
    PartialMock
}

在我写完之后,我想“我可以注入这个就好了,但现在我必须引用我的测试项目和命名空间”。这不适合我。也许是因为我是单位测试的新手并且尽可能地坚持惯例。根据我的理解,测试代码对于正在测试的代码应该是最透明的,这样可以保持尽可能多的重点和清晰度,尽可能地完成它。

我应该不再担心而只是使用我的假工厂吗?我想因为我需要它们来生成假货,就像上面描述的那样,因为我可以访问Fakes属性中的实例化假对象来检查它们的状态。在Rhino Mocks框架中是否有其他实现或可能已经处理这种情况的东西?

1 个答案:

答案 0 :(得分:2)

听起来你的类是动态地实例化对象(可能在一些逻辑结构中像switch语句?)你想要允许用你的FakeFactory对它进行测试吗?

使用FakeFactory并让你的测试类知道测试代码是一个很大的代码气味,表明过于紧密的耦合以及引入你的不必要的关注(实际上,动态实例化已经是一个不必要的问题)。

您应该做的是将工厂模式引入您获取动态对象的方式,并在工厂上设置一个接口,允许您使用RhinoMocks替换它。然后,当您配置Mock对象时,您可以告诉工厂根据需要返回另一个Mock。

所以你的班级最终会看起来像这样:

public class ClassBeingTested
{
    private IFactory _yourFactory;

    public ClassBeingTested(IFactory yourFactory)
    {
        _yourFactory = yourFactory;
    }

    public MethodWithDynamicInstantiation()
    {
        IClass = _yourFactory.GetClassDynamically(someparam);
    }
}

我多年没有使用RhinoMocks所以不会尝试使用某些代码,但是使用这种模式可以最大限度地减少类对动态实例化逻辑的了解,同时还提供了挂钩动态对象模拟的地方。另外删除任何测试代码的知识。