jjzjj

c# - 依赖注入(inject)和模拟框架之间的区别(Ninject vs RhinoMocks 或 Moq)

coder 2023-07-09 原文

Ninject 和 RhinoMocks 或 Moq 等模拟框架有什么区别?我用 Google 搜索了这个,但仍然不清楚。

最佳答案

NinjectDependency Injection对于 .NET。

RhinoMocksMoq都是模拟框架。

现在两者已经没有任何关系了。我真的很难理解这两者,所以我在这里尝试解释一下。

依赖注入(inject):是一种控制反转的实现(姑且称之为)。你不要混淆两者。您正在控制从代码中创建对象。依赖项,例如 IRepository 不会由您的类/代码创建,而是由其他人注入(inject),即依赖项注入(inject)框架。

假设你有

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() 的行。

一个简单的方法是用户工厂方法,这是 IOC 的另一种形式。

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

然后像这样使用它:

IUserRepository rep = RepoFactory.UserRepo;

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

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

模拟框架:天哪,这对我来说就像火箭科学。但是 Steven Sanderson 的书有一个绝妙的简单解释。

我们继续使用 IUserRepository

现在您必须测试一些复杂的 UI/Authentication,无论它取决于 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";
   }
}

现在,当您通过这个 存储库时。如果您的测试失败了,您知道这是其他原因,而不是数据库。

我的例子很简单,但是如果它有大量的接口(interface)。您将需要编写大量 代码,这会导致大量代码膨胀!

所以你可以使用模拟框架在这里编写更少的代码。

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

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

现在我希望您能看到如何利用两者来发挥自己的优势。您可以使用模拟框架创建您的假对象,然后使用依赖注入(inject)在正确的时间连接正确的对象。

对于我较小的 Silverlight 应用程序,我使用 MEF (内置于 .Net4 中)用于依赖注入(inject)。然后,我几乎没有#Ifdef 声明哪些类要Export(或公开)基于#define 符号。所以我只需更改一个 #define,我就可以将我的应用程序切换为到处使用假类。

真心希望对您有所帮助。

关于c# - 依赖注入(inject)和模拟框架之间的区别(Ninject vs RhinoMocks 或 Moq),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5433211/

有关c# - 依赖注入(inject)和模拟框架之间的区别(Ninject vs RhinoMocks 或 Moq)的更多相关文章

  1. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  2. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  3. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  4. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  5. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  6. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  7. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  8. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  9. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  10. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

随机推荐