您的位置:首页 > 理论基础 > 计算机网络

尽可能摆脱对HttpContext的依赖

2014-04-10 17:44 387 查看
  之前谈到对视图进行单元测试时,老赵曾经谈起在视图中应该只使用ViewData中的数据。这不是第一次说起要放弃HttpContext了,自从有了“抽象”这一有利武器后,一切“不和谐”因素都能够被分离。试想在MVP模式中,View和Presenter都使用各自的抽象进行交互,一切Web控件,HttpContext等对象都不复存在了,大家眼中只有“数据”和“模型”。同样,在ASP.NET MVC的Action方法中,也不应该使用HttpContext,这是基于良好的“可测试性”而考虑的。您可能会想,现在的HttpContextBase对象已经可以Mock了啊。没错,它的确“可以”,但是这样做会引起单元测试代码的膨胀,因为测试代码中的相当部分必须关注在测试数据的准备,而不是被测试的功能上。对于一个Action方法来说,它关注的应该是用户与业务逻辑的交互,而不是“如何把HTTP请求转化为可用的数据”。其实说到底,还是要“分离关注点”。

  在ASP.NET MVC中负责“转化数据”的层次为Model Binder。关于这一点,现有的“示例”大都关注把Form或QueryString中的数据转化为Action参数上,不过Model Binder可用的地方其实更多。例如在《最佳实践》的代码中,原本AccountController的Delete方法实现如下:

  public ActionResult Delete(string userName)

  {

  this.MiddleTier.UserManager.Delete(userName);

  Uri urlReferrer = this.Request.UrlReferrer;

  return this.Redirect(urlReferrer.ToString());

  }

  在删除了指定对象之后,页面将跳转到Url Referrer地址中。在上面的代码中,这个值将通过访问Request.UrlReferer来获得。这就使您的Action方法与HttpContext产生了依赖,因此它的单元测试代码就需要这样编写:

  [TestMethod]

  public void DeleteTest()

  {

  string userName = "jeffz";

  Uri urlReferrer = new Uri("http://www.microsoft.com");

  var mockHttpContext = new Mock();

  mockHttpContext.Setup(c => c.Request.UrlReferrer).Returns(urlReferrer);

  var mockController = this.GetMockController();

  mockController.Setup(c => c.MiddleTier.UserManager.Delete(userName)).Verifiable();

  mockController.Object.ControllerContext = new ControllerContext(

  mockHttpContext.Object, new RouteData(), mockController.Object);

  mockController.Object.Delete(userName)...

  }

  在单元测试代码中,我们Mock了一个HttpContextBase对象,让它的Request.UrlReferrer属性返回我们准备好的对象,再构造一个新的ControllerContext并交给Controller。而如果我们的UrlReferrer能够作为Delete方法的参数,那么单元测试代码就会一下子简单很多:

  [TestMethod()]

  public void DeleteTest()

  {

  string userName = "jeffz";

  1688.blog.jp

  ycbjz.blog.jp

  ylbjz.blog.jp

  csbjz.blog.jp

  weibo.blog.jp

  ncbjz.blog.jp

  ykbjz.blog.jp

  xybjz.blog.jp

  xmbjz.blog.jp

  fzbjz.blog.jp

  163.blog.jp

  Uri urlReferrer = new Uri("http://www.microsoft.com");

  var mockController = this.GetMockController();

  mockController.Setup(c => c.MiddleTier.UserManager.Delete(userName)).Verifiable();

  mockController.Object.Delete(userName, urlReferrer)...

  }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: