dependency injection和Mocking框架之间的区别(Ninject vs RhinoMock或Moq)
那么Ninject和RhinoMock或moq之类的模拟框架有什么区别呢? 我谷歌,但它仍然不清楚。
Ninject是.NET的dependency injection 。
RhinoMocks和Moq都是嘲讽的框架。
现在两者都没有任何关系。 我真的很难理解,所以我在这里试着解释一下。
dependency injection :是Inversion of Control的一个实现(我们称之为)。 你不要混淆两者。 你正在控制从你的代码中创build一个对象。 依赖关系,比如说一个IRepository
不会由你的类/代码创build,而是由其他人注入一个dependency injection框架。
可以说你有
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!!
为什么? 问问你自己为什么首先做了一个界面? 所以你可以应付变化 。 那么现在,当你需要改变你的存储库到别的东西。 您必须replace所有具有new MyUserRepo()
。
一个简单的方法是用户工厂方法,这是IOC的另一种forms。
class RepoFactory { public static IUserRepository UserRepo { get {return MyUserRepo();} } }
像这样使用它:
IUserRepository rep = RepoFactory.UserRepo;
现在,当你不得不改变你的仓库时,你只能改变你的工厂。 通过完成所有的工作, dependency injection将它带到下一个层次。 你根本不需要改变代码(或者可能是一些声明)。
IUserRepository repo; //this magically gets the right instance based on some config somewhere.
一个嘲弄的框架 :男孩,这对我来说就像火箭科学。 但史蒂文桑德森的书有一个辉煌的简单的解释。
我们继续与IUserRepository
。
现在你必须testing一些复杂的UI /authentication,不pipe依赖于IUserRepository
。
class UserDisplay : UserControl { UserDisplay(IUserRepository repo) {//display the username or something here.. } }
现在在你的testing中,当你使IUserRepository
成为IUserRepository
一个实例。 如果出现问题,你不知道出了什么问题! 是你的用户控件还是你的数据库连接?
你想让testing更确定,正如有人所说。
所以你做了一个假的用户存储库。
class FakeUserRepo : IUserRepository { public string GetUserName(int id) { return "FakeUser"; } }
所以,现在,当你通过这个假回购。 如果你testing失败,你知道这是另一回事,而不是数据库。
我的例子很简单,但如果它有大量的接口。 你需要写很多的伪代码,它的代码膨胀了很多!
所以你可以使用一个模拟框架在这里写更less的代码。
Moq使用stream畅的界面,相当不错。 使用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
创build假对象变得更容易=)
现在,我希望你看到你如何使用你的优势。 你可以用一个模拟框架来创build你的假对象,然后使用dependency injection来在正确的时间连接正确的对象。
对于我的小型Silverlight应用程序,我使用MEF (内置在.Net4中)进行dependency injection。 然后,我有一些#Ifdef
的基于#define
符号Export
(或公开)类的声明。 所以我只是改变一个#define
,我可以切换我的应用程序在这里和那里使用假类。
真的希望有帮助。
Ninject是控制工具的dependency injection/反转。 你用它来pipe理类之间的依赖关系。
经典的例子是如果你有一个像服务或数据存储库的东西。 不要在整个应用程序中使用具体类,而是要求Ninject内核为您提供一个接口的实例。 这意味着你可以创build多个实现接口的具体类,并在一个地方交换出来。 这在testing中非常有用,但远远超出了这个范围。 很多IoC容器,Ninject也不例外,也会做一些事情,比如pipe理实例生命周期和其他一些东西。 如果你想要每个Web请求使用一个存储库,或者一个类的单个实例,那么Ninject可以很干净地为你处理这种事情。
Moq,RhinoMocks等都是嘲讽的框架,它们会产生假类,让你断言应用程序的其他部分以正确的方式与它们交互。 这些只对testing有用,因为模拟对象除了报告访问方式之外,不提供任何function。
你也许还想看看StructureMap – structuremap.net/structuremap – 他们有一些很好的文章来描述这个模式,Rob Conery也在IoC上做了一些插曲 – http://www.asp.net/mvc/videos/aspnet-mvc -storefront-part-13-dependency-injection – and on Mocking – http://www.asp.net/mvc/videos/aspnet-mvc-storefront-part-12-mocking – 这是一个很好的手表,描述更好比我能做的每件事都要多。