Ваш вопрос касался того, чем фреймворк MS Fakes отличается от NMock, и, похоже, другие ответы решили некоторые из них, но вот еще немного информации о том, чем они одинаковы и чем они отличаются. NMock также похож на RhinoMocks и Moq, поэтому я объединяю их в группу NMock.
Я сразу вижу 3 основных различия между NMock / RhinoMocks / Moq и MS Fakes Framework:
Платформа MS fakes использует сгенерированный код, как и средства доступа в предыдущих версиях Visual Studio, вместо универсальных типов. Если вы хотите использовать фальшивую платформу для зависимости, вы добавляете сборку, которая содержит зависимость, к ссылкам тестового проекта, а затем щелкаете ее правой кнопкой мыши, чтобы сгенерировать тестовые дубли (заглушки или прокладки). Затем, когда вы тестируете, вы фактически вместо этого используете эти сгенерированные классы. NMock использует дженерики для выполнения того же самого (т.е. IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
). На мой взгляд, фреймворк MS Fakes препятствует навигации по коду и рефакторингу изнутри тестов, поскольку вы фактически работаете со сгенерированным классом, а не с вашим реальным интерфейсом.
Фреймворк MS fakes предоставляет заглушки и родинки (прокладки), тогда как NMock, RhinoMocks и Moq предоставляют заглушки и макеты . Я действительно не понимаю решения MS не включать моки, и я лично не поклонник родинок по причинам, описанным ниже.
С помощью фреймворка MS fakes вы предоставляете альтернативную реализацию методов, которые хотите заглушить. В этих альтернативных реализациях вы можете указать возвращаемые значения и отслеживать информацию о том, как и был ли вызван метод. С помощью NMock, RhinoMocks и Moq вы создаете фиктивный объект, а затем используете этот объект для указания заглушенных возвращаемых значений или для отслеживания взаимодействий (независимо от того, вызывались ли методы и как). Я считаю, что подход подделок MS более сложен и менее выразителен.
Чтобы прояснить разницу в том, что предоставляют фреймворки: NMock, RhinoMocks и Moq предоставляют два типа тестовых двойников (заглушки и имитаторы). Фреймворк подделок содержит заглушки и родинки (они их называют прокладками) и, к сожалению, не включает имитацию. Чтобы понять различия и сходства между NMock и MS Fakes, полезно понять, что это за разные типы тестовых двойников:
Заглушки: заглушки используются, когда вам нужно предоставить значения для методов или свойств, которые будут запрашиваться у ваших тестовых двойников тестируемым методом. Например, когда мой тестируемый метод вызывает метод DoesStudentExist () тестового двойника 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 вы создаете совершенно новую реализацию для метода DoesStudentExist (обратите внимание, что он называется DoesStudentExistInt32, потому что фреймворк фейков добавляет типы данных параметров к именам методов, когда он генерирует объекты-заглушки, я думаю, что это затемняет ясность тесты). Честно говоря, реализация 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 fakes вообще не предоставляет имеков. Это означает, что в ваших зарезервированных реализациях (см. Описание заглушек выше) вы должны установить переменные, которые, как вы позже убедитесь, были установлены правильно. Это будет выглядеть примерно так:
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 (полное раскрытие - я написал этот курс и получаю гонорары за просмотры, но я думаю, что это применимо к этому обсуждению, поэтому я включаю его здесь):