Подтвердить что ты не робот

Издевательская без IoC или инъекции зависимостей

Есть ли способ использовать издевательства или подделки в ваших модульных тестах без использования инъекции или инверсии зависимостей?

Я нашел, что этот синтаксис можно использовать с TypeMock Isolator (http://learn.typemock.com/). Это коммерческий продукт, поэтому я надеялся, что другие структуры (такие как RhinoMocks) будут представлять такой синтаксис на определенном этапе.

/// Can mock objects WITHOUT DEPENDENCY INJECTION.

var hand = Isolate.Fake.Instance<Hand>();
var mouth = Isolate.Fake.Instance<Mouth>();
Isolate.Swap.NextInstance<Hand>().With(hand);
Isolate.Swap.NextInstance<Mouth>().With(mouth);
...
//notice we're not passing the mocked objects in.
var brain = new Brain();
brain.TouchIron(iron);
...

Это очень привлекательный для меня тип синтаксиса, все происходит автоматически. Мы можем создать мозг там без каких-либо необходимых зависимостей, и насмешливая структура автоматически заменит зависимости для макетных объектов. Любое тело видел этот тип вещей где-нибудь еще?

Конструктор класса мозга выглядит следующим образом, используя приведенный выше синтаксис,

public Brain()
{
    _hand = new Hand();
    _mouth = new Mouth();
}

В то время как пример инъекции зависимостей будет выглядеть следующим образом:

public Brain(IHand hand, IMouth mouth)
{
    _hand = hand;
    _mouth = mouth;
}

Спасибо.

4b9b3361

Ответ 1

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

public Brain() : this(new Hand(), new Mouth()) { }

Тем не менее, помимо Isolator вы можете проверить последние сборки Pex (0,17), которые включают moles, которые обеспечивают механизм, подобный Isolator Swap.

Ответ 2

Лично я не думаю, что это хорошо.

Для меня DI дает больше пользы, чем просто тестируемость, поэтому нецелесообразно идти от него, даже если какой-то инструмент позволяет это делать. См. Также этот вопрос и первый ответ на него.

Ответ 3

AFAIK, TypeMock - единственная инфраструктура, которая допускает этот сценарий и, вероятно, будет длиться долго. Причина в том, что он использует радикально иной подход к насмешкам.

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

TypeMock использует совершенно другой метод, поскольку использует (неуправляемый).NET Profiling API для перехвата вызовов на любой тип. Это намного сложнее реализовать, поэтому не удивительно, что это коммерческое предприятие.

В любом случае TypeMock против остального мира - это старая и очень оживленная дискуссия. Здесь один возьмется за него (обязательно прочитайте комментарии).

Ответ 4

Moles, структура обхода, которая поставляется с Pex, также позволяет это делать... но с другим синтаксисом.

MHand.New = (me) => {
    new MHand(me) {
        TouchIronIron = iron => {}
    };       
};

Обратите внимание, что ваш пример несовместим.

Ответ 5

Спасибо за это. Это заставило меня подумать о кучах. Я работаю над приложением, которое не предназначено для тестирования и в настоящее время не имеет модульных тестов. Я думаю, что окончательное решение будет состоять в том, чтобы постепенно его перестроить и использовать Rhino Mocks. Раньше я использовал Rhino, и это было здорово.

Я начал понимать, что решение "все в одном", вероятно, является лучшим, то есть Rhino заставит реструктуру использовать полную инверсию управления, которая будет заставлять принимать хорошие проектные решения.

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