Как удалить зависимости от стороннего кода при модульном тестировании? - PullRequest
1 голос
/ 04 ноября 2010

У меня есть некоторый код, который выполняет некоторую унаследованную операцию «база данных», а затем обрабатывает результат. Я хочу написать модульный тест, который проверяет метод, который вызывает унаследованный код, не взаимодействуя с «базой данных».

Мой код выглядит примерно так:

    public static bool CallRoutine(LegacySession session, /* routine params*/)
    {
        try
        {
            LegacyRoutine routine = session.CreateRoutine(/* routine params */);

            routine.Call();

            // Process result

        }
        catch (LegacyException ex)
        {
            // Perform error handling
        }
    }

Если бы это был весь мой код, я бы создал интерфейсы, которые реализуют LegacySession и LegacyRoutine, а затем написал бы модульные тесты, использующие фиктивные реализации этих интерфейсов с использованием MOQ или чего-то подобного. Проблема в том, что у меня нет доступа к коду для LegacyRoutine или LegacySession, поэтому я не могу заставить их реализовать интерфейс.

Есть какие-нибудь идеи о том, как я могу сделать это, не слишком меняя производственный код?

Ответы [ 4 ]

5 голосов
/ 04 ноября 2010

Если вы не можете получить доступ к LegacyRoutine (я предполагаю, что он находится в ссылочной DLL), почему бы просто не создать оболочку для него, а затем включить / выключить различные реализации:

public interface ILegacyWrapper
{
   ILegacyRoutine CreateRoutine(); 
   // etc etc
}

public interface ILegacyRoutine
{
   // put members of LegacyRoutine
}

Знаешь, что я имею в виду?Просто смоделируйте все в оболочках / интерфейсах.

Тогда вы можете пойти:

ILegacyRoutine routine = session.CreateRoutine(/* routine params */)

Где сеанс будет объявлен как ILegacyWrapper ,но реализовано с помощью фиктивного бетона.

Кроме того, само собой разумеется (но я все равно скажу), вы должны рассмотреть структуру DI, чтобы сделать вашу жизнь проще.Иначе вы закончите с IFoo foo = new Foo() (жестко запрограммированной инъекцией) повсюду.

StructureMap - мой выборный DI-яд.

HTH

1 голос
/ 04 ноября 2010

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

0 голосов
/ 04 ноября 2010

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

0 голосов
/ 04 ноября 2010

Поиск C # макет конкретных типов.Извините, я должен бежать, но вот ссылка на первое, что я нашел, что решит вашу проблему (возможно, есть лучшие решения, но это выглядит хорошо):

http://docs.typemock.com/isolator/##typemock.chm/Documentation/CreatingFakesWithAAA.html

Кроме того, проверьте Moq, с которым я имел большой успех в прошлом

...