依赖注入和模拟框架之间的区别(Ninject vs RhinoMock或Moq)

Ska*_*osh 39 .net c# dependency-injection mocking

那么Ninject和像RhinoMock或moq这样的模拟框架之间的区别是什么?我谷歌这个,但它仍然不清楚.

gid*_*eon 98

Ninject是.NET的依赖注入.

RhinoMocksMoq都是模拟框架.

现在两者都没有任何关系.我真的很难理解两者,所以在这里我试着解释一下.

依赖注入:是控制反转的实现(让我们称之为).你不要混淆两者.您正在控制从代码中创建对象.依赖性,比如说IRepository你的类/代码不会创建,而是由其他人注入,依赖注入框架.

让我们说你有

interface IUserRepository
{
 string GetUserName(int id);//one method for simplicity
}
Run Code Online (Sandbox Code Playgroud)

现在你有一个实际的实现:

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

现在到处都是,你将拥有:

IUserRepository repo = new MyUserRepo();//this is bad!!
Run Code Online (Sandbox Code Playgroud)

为什么?问问自己为什么你首先创建了一个界面?所以你可以应对变化.那么现在,当您需要将存储库更改为其他内容时.你必须替换所有的行new MyUserRepo().

一种简单的方法是用户工厂方法,它是IOC的另一种形式.

class RepoFactory
{
 public static IUserRepository UserRepo
 {
  get {return MyUserRepo();}
 } 
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

IUserRepository rep = RepoFactory.UserRepo;
Run Code Online (Sandbox Code Playgroud)

现在,当您必须更改存储库时,您只需要更改工厂.通过完成所有工作,依赖注入将其提升到了一个新的水平.您根本不需要更改代码(或者可能是一些声明).

IUserRepository repo; 
//this magically gets the right instance based on some config somewhere.
Run Code Online (Sandbox Code Playgroud)

模拟框架:男孩这对我来说就像火箭科学.但斯蒂芬桑德森的书中有一个很简单的解释.

我们继续坚持下去IUserRepository.

现在你必须测试一些复杂的UI /身份验证,无论它依赖于什么IUserRepository.

class UserDisplay : UserControl
{
  UserDisplay(IUserRepository repo)
  {//display the username or something here..
  } 
}
Run Code Online (Sandbox Code Playgroud)

现在在你的测试中,当你创建IUserRepository一个实例时MyUserRepo.如果出现问题你不知道出了什么问题!它是您的用户控件还是您的数据库连接?

有人说,你想让测试更具确定性.

所以你做了一个假的用户存储库.

class FakeUserRepo : IUserRepository
{
  public string GetUserName(int id)
  {
    return "FakeUser";
   }
}
Run Code Online (Sandbox Code Playgroud)

所以现在,当你通过这个假的回购.如果你测试失败,你知道它是别的东西,而不是数据库.

我的例子很简单,但如果它有大量的接口.你需要编写很多代码,它的代码很臃肿!

因此,您可以使用模拟框架在此处编写更少的代码.

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
Run Code Online (Sandbox Code Playgroud)

创建假对象变得容易多了=)

现在我希望你能看到如何利用这两者对你有利.您可以使用模拟框架创建虚假对象,然后使用依赖注入在正确的时间连接正确的对象.

对于我较小的Silverlight应用程序,我使用MEF(Inbuilt in .Net4)进行依赖注入.然后我几乎没有#Ifdef关于哪些类Export(或暴露)的声明基于#define 符号.所以我只需更改一个,#define然后我可以将我的应用切换到使用假类.

真的希望这很有帮助.

  • Ninject将返回抽象的实际具体实现.所以你问Ninject一个抽象,它会返回一个注册的具体类型.这可以是具体类型的相同实例,或者每次解析抽象时Ninject都可以实例化一个新实例,具体取决于您配置该注册的方式.Ninject还将处理依赖链,因此您的具体类型所需的任何依赖项也将从Ninject注册中注入.其他流行的DI框架(或IoC容器)包括Unity,Castle Windsor,Autofac和StructureMap. (2认同)

Ric*_*001 5

Ninject是控制工具的依赖项注入/反转。您可以使用它来管理类之间的依赖关系。

经典示例是您是否拥有诸如服务或数据存储库之类的东西。您可以要求Ninject内核为您获取接口的实例,而不是在整个应用程序中使用具体的类。这意味着您可以制作多个实现该接口的具体类,并将它们交换到一个位置。这在测试中非常有用,但远远不止于此。许多IoC容器(Ninject也不例外)还将执行诸如管理实例生命周期和许多其他工作之类的事情。假设您要每个Web请求使用1个存储库,或者要使用一个类的单个实例,这就是Ninject可以非常干净地为您处理的事情。

Moq,RhinoMocks等是模拟框架,它们生成伪造的类供您断言应用程序的其他部分以正确的方式与其交互。这些实际上仅对测试有用,因为模拟的对象除了报告如何访问之外不提供任何功能。

您可能还想看看StructureMap-structuremap.net/structuremap-他们有一些描述模式的好文章,Rob Conery在IoC上也有插曲-http: //www.asp.net/mvc/videos/aspnet-mvc -storefront-part-13-dependency-injection-以及关于模拟-http : //www.asp.net/mvc/videos/aspnet-mvc-storefront-part-12-mocking-这是一个很好的手表,并且描述得更好比我所能了解的要多。