Инъекция носорога издевается над "фальшивой" фабрикой - PullRequest
1 голос
/ 08 июня 2011

Я пытаюсь протестировать класс, который динамически создает объекты и сохраняет их в коллекции.Поскольку мне нужно протестировать логику, которая создает их экземпляры, и операции над этими объектами, я подумал, что было бы неплохо создать вспомогательный фабричный класс, который можно было бы внедрить для тестирования.Вот что я придумала

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 Ответ

2 голосов
/ 09 июня 2011

Похоже, ваш класс создает экземпляры объектов динамически (возможно, в рамках некоторой логической конструкции, такой как оператор 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, поэтому не буду пытаться делать какой-то код, но с этим шаблоном вы минимизируете знания вашего класса о логике динамической реализации, а также предоставляете место для подключения к макетам динамических объектов и дополнительно удаляет любые знания о тестировании кода.

...