Використання IoC для тестування одиниць


97

Як можна використовувати контейнер IoC для тестування одиниць? Чи корисно керувати макетами у величезному рішенні (50+ проектів) за допомогою IoC? Будь-який досвід? Будь-які бібліотеки C #, які добре працюють для її використання в одиничних тестах?


7
@ Марк Семанн був би надто скромним, щоб на це звернути увагу, але якщо вас цікавить це питання, вам слід принаймні знати про AutoFixture
Ruben Bartelink

1
Там добре розмовляють про стосунки між DI та глузуванням над Vimeo Мігелем Кастро: vimeo.com/68390510
GregC

Відповіді:


131

Взагалі кажучи, контейнер DI не повинен бути необхідним для тестування одиниць, оскільки тестування блоку - це все, що стосується розділення обов'язків.

Розглянемо клас, який використовує інжекцію конструктора

public MyClass(IMyDependency dep) { }

У всій вашій програмі може статися, що за цим схований величезний графік залежності IMyDependency, але в одиничному тесті ви все це згладжуєте до одного тестового подвійного .

Ви можете використовувати динамічні макети на зразок Moq або RhinoMocks для створення тестового подвійного, але це не потрібно.

var dep = new Mock<IMyDependency>().Object;
var sut = new MyClass(dep);

У деяких випадках може бути приємно мати контейнер для автоматичного перегляду, але вам не потрібно використовувати той самий контейнер DI, який використовує виробнича програма.


13
погоджено ... якщо випробувальна ціль не містить контейнер IoC як залежність, ваші тести не повинні їх потребувати ... ви збираєтеся видалити більшість об'єктних графіків, коли будете робити свої одиничні тести.
Андерсон Імес

4
@Mark Seemann Це має сенс ... А як щодо тестів на інтеграцію? Тобто, я грав з тестами інтерфейсу, і я зіткнувся з ситуацією, коли мені довелося поділитися композицією root. Будь-які коментарі?
Арніс Лапса

5
@Arnis L .: Для інтеграційних тестів це менш важливо. Ви можете використовувати контейнер DI для підключення компонентів, але якщо так, то, ймовірно, вам знадобиться інша конфігурація для контейнера, ніж у повній програмі - якщо ви не виконаєте підшкірний тест або повний тест на систему, в такому випадку ви можете повторно використовувати конфігурацію програми Container.
Марк Семанн

посилання на журнал
msdn

18

Як можна використовувати контейнер Ioc для тестування одиниць?

IoC буде застосовувати парадигми програмування, які полегшать тестування одиниці в ізоляції (тобто з використанням макетів): використання інтерфейсів, відсутність нових (), без одиночних клавіш ...

Але використання контейнера IoC для тестування насправді не є вимогою, воно просто забезпечить деякі засоби, наприклад, ін'єкцію макетів, але ви можете це зробити вручну.

Чи корисно керувати макетами у величезному рішенні (50+ проектів) за допомогою IoC?

Я не впевнений, що ви маєте на увазі під керуванням макетами за допомогою IoC. У будь-якому випадку контейнери IoC зазвичай можуть робити більше, ніж просто вводити макети, коли справа стосується тестування. І якщо у вас є гідна підтримка IDE, яка робить можливим рефакторинг, чому б не використовувати його?

Будь-який досвід?

Так, для величезного рішення вам як ніколи потрібне рішення, не схильне до помилок та несприятливе для рефакторингу (тобто через безпечний контейнер IoC типу або хорошу підтримку IDE).


17

Я часто використовую контейнер IoC у своїх тестах. Зрозуміло, вони не є "одиничними тестами" в чистому сенсі. IMO Вони більш BDDish та полегшують рефакторинг. Тести існують, щоб дати вам впевненість рефактору. Погано написані тести можуть бути як заливка цементу у ваш код.

Розглянемо наступне:

[TestFixture]
public class ImageGalleryFixture : ContainerWiredFixture
{
    [Test]
    public void Should_save_image()
    {
        container.ConfigureMockFor<IFileRepository>()
            .Setup(r => r.Create(It.IsAny<IFile>()))
            .Verifiable();

        AddToGallery(new RequestWithRealFile());

        container.VerifyMockFor<IFileRepository>();
    }

    private void AddToGallery(AddBusinessImage request)
    {
        container.Resolve<BusinessPublisher>().Consume(request);
    }
}

При додаванні зображення до галереї відбувається кілька речей. Зображення змінюється за розміром, створюється ескіз, а файли зберігаються на AmazonS3. Використовуючи контейнер, я можу легше виділити лише поведінку, яку я хочу перевірити, що в цьому випадку є складовою частиною.

Автомобільне розширення контейнера стане в нагоді при використанні цієї техніки: http://www.agileatwork.com/auto-mocking-unity-container-extension/


8
+1 для фрази "як заливка цементу у ваш код". Я постійно почав його використовувати.
Андрій Пастух

2

Використання контейнерів з можливістю дозвіл незареєстрованими / Невідомими послугами , такими як SimpleInjector , DryIoc (його шахта) може повертати знущається для ще не реалізованих інтерфейсів.

Це означає, що ви можете почати розробку, використовуючи першу просту реалізацію та її знущаються залежності, і замінювати їх справжніми речами в процесі просування.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.