梦想成现实:用xUnit.net在单元测试中实现构造函数依赖注入

发表于:2011-8-09 10:40

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:dudu    来源:51Testing软件测试网采编

  自从将开发架构迁移至DDD(领域驱动开发),就开始正式使用“构造函数依赖注入”,由CNBlogs.Infrastructure.CrossCutting.IoC(IoC容器抽象层,目前默认容器用的是Unity)负责。

  通过构造函数进行依赖注入,避免了在代码中针对所依赖的接口创建相应的实例,这个工作改由IoC容器在运行时自动完成。我们主要在APS.NETMVC的Controller与应用层的服务实现中使用。

  比如下面的APS。NETMVCController示例代码:

  publicclassAdminController:Controller
  {
  privateIBlogSiteManagementService_blogSiteService;
  publicAdminController(IBlogSiteManagementServiceblogSiteService)
  {
  _blogSiteService=blogSiteService;
  }
  }

  ASP.NETMVC会在运行时通过IoC容器获取IBlogSiteManagementService的实现,并传递给AdminController的构造函数。(这个操作是在DefaultControllerFactory.Create方法中完成的,参见ASP.NETMVC源代码DefaultControllerFactory.cs第259行)

  注:要让ASP.NETMVC支持依赖注入,需要实现IDependencyResolver接口,并将所有MVC自带的IController的实现注册到你所用的IoC容器。

  自从成功用上了依赖注入,差点成为依赖注入“控”,看到需要依赖的地方,就想着注入。

  爱情是不是也可以依赖注入?在你心中声明一下你心仪的女孩的样子,然后丘比特就会给你注入。。。

  进入正题。。。

  改变博客园团队开发方式的不仅是DDD(领域驱动开发),还有TDD(测试驱动开发)。有了轻微的依赖注入“控”,在写测试代码时,我们不由自主地想到了测试类的构造函数依赖注入。

  可是尝试了几个主流的.NET测试框架(MsTest,NUnit,MbUnit,xUnit.net),连带参数的构造函数都不支持,更别谈构造函数依赖注入。

  搜遍互联网,也没发现有人试图解决这个问题。

  刚开始TDD时,我们就被这个问题困扰,似乎是一个暂时无法解决的问题。。。于是,这就成为了一个可望而不可及的梦想。

  不能注入,那只能在无参构造函数中手动获取所依赖接口的实现实例,示例代码(用的是xUnit.net)如下:

  publicclassMyPostList
  {
  privateIBlogSiteManagementService_blogSiteService;
  publicMyPostList()
  {
  _blogSiteService=IoCFactory.Instance.CurrentContainter
  .Resolve<IBlogSiteManagementService>();
  }
  [Fact]publicvoidGet_My_Recent_Admin_Posts()
  {
  Assert.NotNull(_blogSiteService);
  }
  }

  昨天开始,我们决定攻克这个难题,比较了几个测试框架,最终选择了xUnit.net(MsTest由于没有开源,根本没考虑)。

  选择的理由是xUnit.net是NUnit的开发者开发的,扩展性很好。

  解决的思路很简单:找到测试运行时测试类的实例化是在哪进行的。

  有了源代码,让这个寻找过程轻松了很多。

  xUnit.net在VisualStudio中也是通过TestDriven.net加载的,所以打开xUnit的源代码,直奔主题,进入xunit.runner.tdnet项目,打开TdNetRunner.cs,然后顺藤摸瓜:

  Xunit.TestRunner()>Xunit.ExecutorWrapper.RunClass()>
  Xunit.Sdk.Executor.RunTests()>TestClassCommandRunner.Execute()>
  TestCommandFactory.Make()>LifetimeCommand.Execute()

  在Xunit.Sdk.LifetimeCommand.Execute(object testClass)中发现了瓜:

  publicoverrideMethodResultExecute(objecttestClass)
  {
  if(testClass==null)
  testClass=method.CreateInstance();
  }

31/3123>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号