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

2024-03-08

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


Ninject http://ninject.org/ is 依赖注入 http://en.wikipedia.org/wiki/Dependency_injection对于.NET。

犀牛模型 http://www.ayende.com/projects/rhino-mocks.aspx and Moq http://code.google.com/p/moq/都是模拟框架。

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

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

假设你有

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!!

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

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

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

并像这样使用它:

IUserRepository rep = RepoFactory.UserRepo;

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

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

模拟框架:天哪,这对我来说就像火箭科学。但史蒂文·桑德森的书有一个精彩而简单的解释。

我们继续与IUserRepository.

现在你必须测试一些复杂的 UI/身份验证,无论这取决于什么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";
   }
}

所以现在,当你通过这个fake回购。如果您的测试失败,您知道这是其他原因,而不是数据库。

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

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

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 http://mef.codeplex.com/(内置于.Net4)用于依赖注入。然后我就很少了#Ifdef关于哪些类的声明Export(或暴露)基于#define象征。所以我只换一个#define我可以将我的应用程序切换为到处使用假类。

真的希望这有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

依赖注入和模拟框架之间的区别(Ninject vs RhinoMocks 或 Moq) 的相关文章

  • 在c#中执行Redis控制台命令

    我需要从 Redis 控制台获取 客户端列表 输出以在我的 C 应用程序中使用 有没有办法使用 ConnectionMultiplexer 执行该命令 或者是否有内置方法可以查找该信息 CLIENT LIST是 服务器 命令 而不是 数据库
  • 如何填充 ToolStripComboBox?

    我发现它很难将数据绑定到ToolStripComboBox 好像没有这个ValueMember and DisplayMember特性 怎么绑定呢 访问toolstripcombobox中包装的组合框并访问其ValueMember Disp
  • Visual Studio 在构建后显示假错误

    我使用的是 Visual Studio 2017 构建后 sln在调试模式下 我收到错误 但是 当我通过双击错误列表选项卡中的错误来访问错误时 错误会从页面中消失 并且错误数量也会减少 我不太确定这种行为以及为什么会发生这种情况 有超过 2
  • 使用 GCP 的数据存储区时如何区分代码是在模拟器中运行还是在 GKE 中运行

    按照中给出的说明进行操作后 我不确定是否遗漏了任何内容https cloud google com datastore docs tools datastore emulator https cloud google com datasto
  • 使用 LINQ to SQL 时避免连接超时的最佳实践

    我需要知道在 net 应用程序中使用 LINQ to SQL 时避免连接超时的最佳实践 特别是在返回时IQueryable
  • 告诉 Nancy 将枚举序列化为字符串

    Nancy 默认情况下在生成 JSON 响应时将枚举序列化为整数 我需要将枚举序列化为字符串 有一种方法可以通过创建来自定义 Nancy 的 JSON 序列化JavaScript 原始转换器 https github com NancyFx
  • 将 Long 转换为 DateTime 从 C# 日期到 Java 日期

    我一直尝试用Java读取二进制文件 而二进制文件是用C 编写的 其中一些数据包含日期时间数据 当 DateTime 数据写入文件 以二进制形式 时 它使用DateTime ToBinary on C 为了读取 DateTime 数据 它将首
  • 为什么可以通过ref参数修改readonly字段?

    考虑 class Foo private readonly string value public Foo Bar ref value private void Bar ref string value value hello world
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • WPF DataGridTemplateColumn 组合框更新所有行

    我有这个 XAML 它从 ItemSource 是枚举的组合框中选择一个值 我使用的教程是 http www c sharpcorner com uploadfile dpatra combobox in datagrid in wpf h
  • 在屏幕上获取字符

    我浏览了 NCurses 函数列表 似乎找不到返回已打印在屏幕上的字符的函数 每个字符单元格中存储的字符是否有可访问的值 如果没有的话Windows终端有类似的功能吗 我想用它来替换屏幕上某个值的所有字符 例如 所有a s 具有不同的特征
  • DataTable.GetChanges() 不断返回 NULL

    我正在尝试获取存在于的所有行allData但不在removeData public static DataTable RemoveDuplicateRows DataTable allData DataTable removeData re
  • String.Empty 与 "" [重复]

    这个问题在这里已经有答案了 可能的重复 String Empty 和 有什么区别 https stackoverflow com questions 151472 what is the difference between string
  • 将数组作为参数传递

    如果我们修改作为方法内参数传递的数组的内容 则修改是在参数的副本而不是原始参数上完成的 因此结果不可见 当我们调用具有引用类型参数的方法时 会发生什么过程 这是我想问的代码示例 using System namespace Value Re
  • 可访问性不一致:参数类型的可访问性低于方法

    我试图在两个表单之间传递一个对象 基本上是对当前登录用户的引用 目前 我在登录表单中有一些类似的内容 private ACTInterface oActInterface public void button1 Click object s
  • 使用 omp_set_num_threads() 将线程数设置为 2,但 omp_get_num_threads() 返回 1

    我有以下使用 OpenMP 的 C C 代码 int nProcessors omp get max threads if argv 4 NULL printf argv 4 s n argv 4 nProcessors atoi argv
  • 为boost python编译的.so找不到模块

    我正在尝试将 C 代码包装到 python 中 只需一个类即可导出两个函数 我编译为map so 当我尝试时import map得到像噪音一样的错误 Traceback most recent call last File
  • 如何使用 C++11 using 语法键入定义函数指针?

    我想写这个 typedef void FunctionPtr using using 我该怎么做呢 它具有类似的语法 只不过您从指针中删除了标识符 using FunctionPtr void 这是一个Example http ideone
  • OpenCV SIFT 描述符关键点半径

    我正在深入研究OpenCV的SIFT描述符提取的实现 https github com Itseez opencv blob master modules nonfree src sift cpp 我发现了一些令人费解的代码来获取兴趣点邻域

随机推荐