Ваше запитання стосувалося того, чим рамка MS Fakes відрізняється від NMock, і, здається, інші відповіді вирішили деякі з них, але ось додаткова інформація щодо того, наскільки вони однакові та чим вони відрізняються. NMock також схожий на RhinoMocks і Moq, тому я групую їх у NMock.
Є три основні відмінності, які я бачу прямо між NMock / RhinoMocks / Moq та MS Fakes Framework:
Фреймворк MS використовує генерований код, подібно до Accessors в попередніх версіях Visual Studio замість загальних типів. Коли ви хочете використовувати фейк-фреймворк для залежності, ви додаєте збірку, яка містить залежність, до посилань тестового проекту, а потім клацніть правою кнопкою миші на ньому, щоб генерувати тестові подвійні елементи (заглушки або прокладки). Тоді, коли ви тестуєте, ви фактично використовуєте ці створені класи замість цього. NMock використовує дженерики, щоб досягти того ж (тобто IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
). На мою думку, рамковий підхід MS Fakes гальмує кодову навігацію та рефакторинг зсередини тестів, оскільки ви насправді працюєте з генерованим класом, а не з реальним інтерфейсом.
Підроблені фреймворки MS постачають заглушки і кроти (прокладки), тоді як NMock, RhinoMocks і Moq - все це заглушки і макети . Я дійсно не розумію рішення МС не включати знущань, і я особисто не шанувальник кротів з причин, описаних нижче.
За допомогою фейкової системи MS ви надаєте альтернативну реалізацію методів, які ви хочете заглушити. У межах цих альтернативних реалізацій можна вказати повернені значення та відстежити інформацію про те, як або якщо метод викликався. За допомогою NMock, RhinoMocks та Moq ви генеруєте макетний об'єкт, а потім використовуєте цей об'єкт, щоб вказати стержневі значення повернення або відстежувати взаємодії (чи називались способи). Мені здається, що підробка MS підробка більш складна і менш виразна.
Щоб уточнити різницю в тому, що надають рамки: NMock, RhinoMocks і Moq забезпечують два типи тестових пар (заглушки та макети). Рамка підробок містить заглушки та родимки (вони називають їх лайми), і, на жаль, не включає макети. Для того, щоб зрозуміти відмінності та схожість між NMock та MS Fakes, корисно зрозуміти, що таке різні типи парних пар:
Заглушки: Заглушки використовуються, коли вам потрібно вказати значення для методів чи властивостей, які будуть запропоновані вашим тестовим подвоєнням методом тестування. Наприклад, коли мій тестовий метод викликає метод DoesStudentExist () тесту IStudentRepository подвійний, я хочу, щоб він повернув істину.
Ідея заглушок у підробках NMock та MS однакова, але з NMock ви б зробили щось подібне:
Stub.On(mockStudentRepository).Method("DoesStudentExist").Will(Return.Value(true));
І з MSFakes ви зробите щось таке:
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
DoesStudentExistInt32 = (studentId) => { return new Student(); }
};
Зауважте у прикладі MS Fakes, що ви створюєте абсолютно нову реалізацію методу DoesStudentExist (Зауважте, що він називається DoesStudentExistInt32, оскільки фейк-фрейм додає типи даних параметрів до імен методу, коли він генерує об'єкти stub, я думаю, це не приховує чіткість тести). Якщо чесно, реалізація NMock також помиляє мене, оскільки для імені методу використовується рядок. (Вибачте, якщо я зрозумів неправильно, як NMock призначений для використання.) Цей підхід дійсно гальмує рефакторинг, і я настійно рекомендую RhinoMocks або Moq через NMock з цієї причини.
Макети: Макети використовуються для перевірки взаємодії між вашим тестовим методом та його залежностями. З NMock ви це робите, встановлюючи очікування, подібні до цього:
Expect.Once.On(mockStudentRepository).Method("Find").With(123);
Це ще одна причина, чому я віддаю перевагу RhinoMocks і Moq над NMock, NMock використовує старіший стиль очікування, тоді як RhinoMocks і Moq підтримують підхід Arrange / Act / Assert, де ви вказуєте очікувані взаємодії як твердження в кінці тесту, як це. :
stubStudentRepository.AssertWasCalled( x => x.Find(123));
Ще раз зауважте, що RhinoMocks використовує лямбда замість рядка для ідентифікації методу. MS фейк-фреймс взагалі не дає макетів. Це означає, що у своїх заглушених реалізаціях (див. Опис заглушок вище) ви повинні встановити змінні, які згодом переконаєтесь, що вони встановлені правильно. Це виглядатиме приблизно так:
bool wasFindCalled = false;
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository()
{
DoesStudentExistInt32 = (studentId) =>
{
wasFindCalled = true;
return new Student();
}
};
classUnderTest.MethodUnderTest();
Assert.IsTrue(wasFindCalled);
Я вважаю, що цей підхід є дещо заплутаним, оскільки вам потрібно відстежити виклик у заглушці, а потім підтвердити його пізніше в тесті. Я вважаю, що приклади NMock, і особливо RhinoMocks, є більш виразними.
Кроти (Шимс): Чесно кажучи, я не люблю родимок, через їх потенціал до неправильного використання. Одне з речей, яке мені дуже подобається в одиничному тестуванні (і TDD зокрема), - тестування вашого коду допомагає зрозуміти, де ви написали поганий код. Це тому, що перевірити погано записаний код складно. Це не вірно при використанні родимок, тому що родимки фактично розроблені для того, щоб ви могли протестувати на залежності, які не вводяться, або перевірити приватні методи. Вони працюють аналогічно заглушкам, за винятком того, що ви використовуєте ShimsContext так:
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}
Мене турбує кайфове те, що люди почнуть сприймати їх як "простіший спосіб одиничного тестування", оскільки це не змушує вас писати код так, як слід. Для більш повної написання цієї концепції дивіться цей пост:
Для отримання додаткової інформації про деякі проблеми, пов’язані з фейками, перегляньте ці повідомлення:
Якщо вам цікаво вивчити RhinoMocks, ось відео з навчального курсу Pluralsight (повне розкриття інформації - я написав цей курс і отримую винагороду за перегляд, але, думаю, це стосується цієї дискусії, тому я включаю її тут):