Ответ 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
, и я могу переключить свое приложение на использование поддельных классов здесь и там.
Действительно надеюсь, что это было полезно.