【问题标题】:Mocking HttpContext in MVC **Outside** of the Controller在 MVC **外部**控制器中模拟 HttpContext
【发布时间】:2011-08-03 08:28:42
【问题描述】:

场景

我们正在开发一个新的 MVC Web 项目,并尝试遵循本文http://codebetter.com/iancooper/2008/12/03/the-fat-controller/ 中描述的 Skinny Controller 模式

作为我们操作之一的一部分,我们正在从缓存中检索一些导航数据(菜单结构)。

问题

我为了维护我们希望在 ViewModel 中进行缓存检查调用的瘦控制器模式,我们已经尝试过并且我们知道使用以下代码有效。

var cachedCategories = (List<Category>)HttpContext.Current.Cache["Categories"];
if (cachedCategories == null) {
       cachedCategories = _service.GetCategories().ToList<Category>();
       HttpContext.Current.Cache["Categories"] = cachedCategories;
}

但是,在进行单元测试时,我们遇到了问题。由于我们没有直接将 HttpContext 传递到 ViewModel,我们不知道如何去模拟 HttpContext。

我们使用的是 Moq,虽然我们有一些选项(一种是在实例化时将上下文从控制器传递到视图模型),但这些选项需要更改代码才能使测试正常工作。

有人有什么建议吗?

【问题讨论】:

  • 可以在控制器上放置一个可分配给局部变量的属性,如果它为空,则分配 HttpContect.Current,并返回 HttpContextBase,您可以从测试中分配 HttpContextBase。如果这有意义的话。
  • 事实上,如果您使用的是 IoC 框架,您可以自动将 HttpContext.Current 分配给 HttpContextBase 属性(或构造函数),那么您可以只拥有一个字段或自动属性。 (嗯,我认为这是关于此的博文;))
  • 仅出于测试目的添加属性是我们提出的选项之一,但我们宁愿不这样做。我们试图避免纯粹为了测试而添加代码。
  • 您添加的属性不是纯粹用于测试,而是抽象出一个依赖项。这只是如何知道要采取的海滩方法,因为我不知道您是否使用了 IoC 框架。

标签: c# asp.net-mvc-3 moq viewmodel httpcontext


【解决方案1】:

模拟 HttpContext 是一项巨大的工作,因为它是您一生中将看到的最大对象之一,所以最好不要模拟它。(http://volaresystems.com/Blog/post/Dont-模拟-HttpContext.aspx) 无论如何,您可以使用 MVCcontrib (http://www.codeplex.com/mvcContrib) 中的文件 MvcMockHelps 显示它是如何完成的。

【讨论】:

  • 不模拟它不是一个选项,因为测试失败并出现对象引用异常。
  • 您可以使用 MvcContrib 项目中的 MvcMockHelps,如我的回答所示 HttpContext 有数百个依赖项,您也应该模拟这些依赖项,我会选择 MvcMockHelps :-)
  • 我快速浏览了 MvcContrib,虽然我同意它非常有用,但我不确定我是否理解它在这种情况下如何帮助我。 “TestHelper 通过提供一个控制器工厂来提供帮助,该工厂创建具有正确初始化的内部数据成员的控制器。”我的问题是我试图模拟 ViewModel 内控制器的 HttpContext outside
【解决方案2】:

最终我们选择修改代码以简化测试。

正如我在原始问题中提到的那样,我们通过在实例化时将 HttpContext 传递给 ViewModel 来实现这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-27
    • 2016-12-16
    • 2019-11-16
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多