2010-08-20 164 views
1

ASP.NET MVC已经成为一个单元测试框架很长的路要走(相对于web表单)。但是,我们经常面对一些剩余的猪,比如FormsAuthentication,我通常将它们包装在某种类型的UserSession对象中,以保持其清洁和可测试性。有一天,我意识到我是用在使用Server.Mappath我的控制器动作,和而像MvcContrib可以很容易(ISH)嘲笑当前请求,我发现自己下去创建FileSystemService类的路径环绕操作与文件系统。好处是您可以获得一个严格的API,仅暴露您需要的方法,并且很容易在测试中存根/模拟。缺点是它是另一个构造函数依赖项。ASP.NET MVC单元测试的HttpContext

什么对这种情况多所社区的事情吗?试图使控制器尽可能轻便灵活时,你在哪里画线?

+0

绝对是主观的。什么是轻便/灵活的控制器?这是值得商榷的。 – jfar 2010-08-20 15:31:25

+0

更具体地说,那么当你停止尝试摆脱依赖于Request/HttpContext的静态框架方法 – RickP 2010-08-20 15:33:42

+0

好的,改变你的问题。 – jfar 2010-08-20 15:43:20

回答

1

我一般会画点在哪里,你需要真正得到的东西做的线(即有人想使用你所编写的代码)。如果另需半天时间来写你的服务等,以及你的最后期限是迫在眉睫,那么有些东西是最好的留给...

1

记住,ASP.NET MVC已经取代了封闭的HttpContext更多的测试 - 友好HttpContextBase,你可以嘲笑提供你的测试与服务器的您所选择的实现*,要求*,响应*等

你只需要设置控制器ControllerContext提供您的测试背景:。

controllerUnderTest.ControllerContext = new ControllerContext(testHttpContext, new RouteData(), controllerUnderTest); 
0

这是一个很大的问题!我做同样的事情 - 包装HttpContext依赖关系,以便它们可以被看见,倒置和模拟。

我绘制了控制器行以验证帖子值并将呼叫保存或传递给任务层。因此,如果我必须验证,保存一些数据,如果首选客户进行购买,记录某些内容等,则发送电子邮件至市场营销部门,这太多了。我把它放在任务层,让我的控制器调用任务层。大多数依赖关系然后浮动到任务层构造函数并从控制器中出来。我的一般经验法则是:如果你被要求在你的应用上创建一个Silverlight或其他UI,你会完全重写它吗?控制器应该坚持呈现逻辑。如果你可以刮掉表示层并放置另一个表面层,我认为这会给你最好的未来打样。

当然,你画线的地方取决于你和你的应用程序。请参阅Who Can Help Me(基于Sharp Architecture),以获取有关任务层和骨干控制器的更多信息。

0

还有周围的事物,喜欢的HttpContext这些包装,以使测试更加简单:

http://www.codethinked.com/post/2008/12/04/Using-SystemWebAbstractions-in-Your-WebForms-Apps.aspx

所以总结起来:

获取的System.Web。抽象

使用的HttpContext基地作为参数,而不是HttpContext的:

public void SomeMethod(HttpContextBase context) 
{ 
} 

调用方法包裹你的真实HTTP上下文

HttpContextBase contextBase = new HttpContextWrapper(context); 
SomeMethod(contextBase); 

可以提供假货像这样(使用起订量为例):

var context = new Mock<HttpContextBase>(); 
context.Setup(x => x.Request.QueryString).Returns(new NameValueCollection { { "Id", "5" } });