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

Разница между инжекцией зависимостей и фальсификацией (Ninject vs RhinoMock или Moq)

Так в чем же разница между Ninject и насмешливой структурой, такой как RhinoMock или moq? Я google'd это, но это все еще неясно.

4b9b3361

Ответ 1

Ninject Инъекция зависимостей для .NET.

RhinoMocks и Moq - оба издевательские рамки.

Теперь оба не имеют ничего общего друг с другом. Мне действительно было трудно понять и то и другое, поэтому я пытаюсь объяснить.

Инъекция зависимостей: это реализация (позволяет вызвать) инверсии управления. Вы не путаете этих двух. Вы берете на себя управление созданием объекта из своего кода. Зависимости, например, говорят, что IRepository не будут созданы вашими классами/кодом, а вместо этого будут введены кем-то другим, инфраструктурой инъекций зависимостей.

Допустим, у вас есть

interface IUserRepository
{
 string GetUserName(int id);//one method for simplicity
}

Теперь у вас есть реальная реализация:

class MyUserRepo : IUserRepository
{
 string GetUserName(int id)
 {
  //grab your username from your data base here.
 } 
}

Теперь по всему месту у вас будет:

IUserRepository repo = new MyUserRepo();//this is bad!!

Почему? Спросите себя, почему вы создали интерфейс в первую очередь? Таким образом, вы можете справиться с изменением. Ну, теперь, когда вам нужно изменить свой репозиторий на что-то еще. Вы должны заменить все строки с new MyUserRepo().

Простым методом является пользовательский метод factory, который является другой формой IOC.

class RepoFactory
{
 public static IUserRepository UserRepo
 {
  get {return MyUserRepo();}
 } 
}

И используйте его следующим образом:

IUserRepository rep = RepoFactory.UserRepo;

Теперь, когда вам нужно изменить свой репозиторий, вам нужно изменить только ваш factory. Включение зависимостей переходит на следующий уровень, выполняя всю работу. Вам вообще не нужно менять код (или, может быть, несколько объявлений).

IUserRepository repo; 
//this magically gets the right instance based on some config somewhere.

Отказывающая рамочка. Мальчик, это для меня как ракетостроение. Но книга Стивена Сандерсона имела блестящее простое объяснение.

Продолжаем работу с IUserRepository.

Теперь вам нужно проверить сложный интерфейс/аутентификацию, что зависит от IUserRepository.

class UserDisplay : UserControl
{
  UserDisplay(IUserRepository repo)
  {//display the username or something here..
  } 
}

Теперь в вашем тесте, когда вы делаете IUserRepository экземпляр MyUserRepo. Если что-то пойдет не так, вы не знаете, что пошло не так! Это ваш пользовательский контроль или подключение к базе данных?

Вы хотите сделать тест более детерминированным, как сказал кто-то.

Итак, вы создаете поддельный репозиторий пользователей.

class FakeUserRepo : IUserRepository
{
  public string GetUserName(int id)
  {
    return "FakeUser";
   }
}

Итак, когда вы передаете это поддельное репо. Если вы испытываете неудачу, вы ЗНАЕТЕ это что-то другое, а не база данных.

Мой пример был прост, но если его большое количество интерфейсов. Вам нужно написать много фальшивого кода, его много раздувать код!

Итак, вы можете использовать насмешливую структуру, чтобы писать меньше кода здесь.

Moq использует свободный интерфейс и довольно приятный. Использование Moq будет выглядеть так:

var fakeUserRepo = new Mock<IUserRepository>();
fakeUserRepo.Setup(f => f.GetUserName(It.IsAny<int>)).Returns("FakeUser");
//does the same thing as the class declaration
fakeUserRepo.Object;//this returns fake object of type IUserRepository

Создание поддельных объектов становится намного проще =)

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

Для моих небольших приложений Silverlight я использую MEF (встроенный в .Net4) для инъекций зависимостей. И тогда у меня мало #Ifdef в объявлениях, для которых классы Export (или выставляются) на основе символа #define. Поэтому я просто меняю один #define, и я могу переключить свое приложение на использование поддельных классов здесь и там.

Действительно надеюсь, что это было полезно.

Ответ 2

Ninject - это инъекция/инверсия зависимостей инструмента управления. Вы используете это для управления зависимостями между классами.

Классический пример: если у вас есть что-то вроде службы или репозитория данных. Вместо того, чтобы использовать конкретный класс во всем приложении, вы можете попросить ядро ​​Ninject получить экземпляр интерфейса. Это означает, что вы можете создавать несколько конкретных классов, реализующих интерфейс, и заменять их в одном месте. Это очень полезно при тестировании, но выходит далеко за рамки этого. Многие контейнеры IoC, Ninject не являются исключением, также будут делать такие вещи, как управлять жизненными циклами экземпляра и множеством других вещей. Скажем, если вы хотите использовать 1 репозиторий для каждого веб-запроса или один экземпляр класса, то, что Ninject может позаботиться о вас очень чисто.

Moq, RhinoMocks и т.д. являются издевательскими фреймворками, они генерируют поддельные классы, чтобы вы утверждали, что другие части приложения взаимодействуют с ними правильным образом. Они действительно полезны только для тестирования, потому что издевавшиеся объекты не предоставляют никакой функциональности, не сообщая о том, как они были доступны.

Вы также можете проверить StructureMap - structuremap.net/structuremap - у них есть хорошие статьи, описывающие шаблон, а также Rob Conery делает эпизоды на IoC - http://www.asp.net/mvc/videos/aspnet-mvc-storefront-part-13-dependency-injection - и на Mocking - http://www.asp.net/mvc/videos/aspnet-mvc-storefront-part-12-mocking - это хорошие часы и описывают намного лучше, чем я могу, что каждый около.