Ответ 1
Ваш вопрос касался того, как структура MS Fakes отличается от NMock, и, похоже, другие ответы разрешили некоторые из них, но вот еще несколько сведений о том, как они совпадают и как они отличаются. NMock также похож на RhinoMocks и Moq, поэтому я группирую их с NMock.
Есть 3 основных различия, которые я вижу сразу между NMock/RhinoMocks/Moq и Framework Faces:
-
Структура фреймов MS использует сгенерированный код, как и Accessors в предыдущих версиях Visual Studio вместо общих типов. Если вы хотите использовать фальшивую фреймворк для зависимости, вы добавляете сборку, содержащую зависимость, к ссылкам тестового проекта, а затем щелкните ее правой кнопкой мыши, чтобы создать тестовые двойники (заглушки или прокладки). Затем, когда вы тестируете, вы фактически используете эти сгенерированные классы. NMock использует дженерики для достижения того же самого (т.е.
IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
). На мой взгляд, рамочный подход MS Fakes запрещает навигацию и рефакторинг кода изнутри тестов, так как вы фактически работаете с сгенерированным классом, а не с вашим реальным интерфейсом. -
Структура фальсификации MS снабжает окурки и кроты (прокладки), в то время как NMock, RhinoMocks и Moq все предоставляют заглушки и mocks. Я действительно не понимаю решение MS не включать в себя издевательства, и я лично не поклонник родинок по причинам, описанным ниже.
-
С фреймворком MS fakes вы предоставляете альтернативную реализацию методов, которые вы хотите заглушить. В рамках этих альтернативных реализаций вы можете указать возвращаемые значения и отслеживать информацию о том, как или был вызван метод. С помощью NMock, RhinoMocks и Moq вы создаете макет объекта, а затем используете этот объект, чтобы указать затушенные возвращаемые значения или отслеживать взаимодействия (как и как были вызваны методы). Я считаю подход подделок MS более сложным и менее выразительным.
Чтобы прояснить разницу в том, что обеспечивают фреймворки: NMock, RhinoMocks и Moq предоставляют два типа тестовых двойников (заглушки и макеты). Рамки подделок обеспечивают заглушки и кроты (они называют их прокладками) и, к сожалению, не включают в себя mocks. Чтобы понять различия и сходства между NMock и MS Fakes, полезно понять, каковы эти различные типы тестовых удвоений:
Stubs: Опоры используются, когда вам нужно предоставить значения для методов или свойств, которые будут заданы вашим тестовым удваиванием тестируемым методом. Например, когда мой тестируемый метод вызывает метод IsStudentExist() двойного тестового теста IStudentRepository, я хочу, чтобы он возвращал true.
Идея окурков в подделках 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 вы создаете совершенно новую реализацию для метода DoStudentExist (обратите внимание, что он называется DoesStudentExistInt32, потому что фальшивая инфраструктура добавляет типы данных параметров к именам методов, когда генерирует объекты-заглушки, я думаю, что это затеняет ясность тестов). Честно говоря, реализация NMock также меня пугает, потому что она использует строку для идентификации имени метода. (Простите меня, если я неправильно понял, как NMOCK предназначен для использования.) Этот подход действительно тормозит рефакторинг, и я настоятельно рекомендую RhinoMocks или Moq по NMock по этой причине.
Mocks: Mocks используются для проверки взаимодействия между тестируемым методом и его зависимостями. С 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); };
}
Мое беспокойство в отношении прокладок заключается в том, что люди начнут рассматривать их как "более простой способ unit test", потому что это не заставляет вас писать код так, как вам следует. Для более полной записи этой концепции см. Этот пост:
Для получения дополнительной информации о некоторых проблемах, связанных с фреймворками, взгляните на эти сообщения:
Если вы заинтересованы в изучении RhinoMocks здесь учебного видео Pluralsight (полное раскрытие информации - я написал этот курс и получаю роялти за просмотры, но я думаю, что это относится к этому обсуждению, поэтому я включаю его здесь):