- 浏览: 256972 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (293)
- web (1)
- [随笔分类]项目管理 (30)
- [随笔分类]WCF (14)
- 未分类 (1)
- [随笔分类]Linq (4)
- [随笔分类]C#基础 (24)
- 项目 (1)
- [网站分类]3.非技术区(技术之外的文章,但不要涉及任何政治内容) (8)
- [网站分类]1.首页原创精华.NET区(包含架构设计、设计模式)(对首页文章的要求:原创、高质量、经过认真思考并精心写作) (9)
- [随笔分类]Ubuntu (4)
- ASP.Net (1)
- [网站分类]2..NET新手区(用于发表不合适发表在首页的.NET技术文章,包括小经验、小技巧) (30)
- [随笔分类]ASP.NET MVC (20)
- [随笔分类]ASP.NET (3)
- [随笔分类]程序员厨房 (4)
- [随笔分类]英语学习 (28)
- [网站分类]4.其他技术区 (1)
- [随笔分类]Silverlight (12)
- [随笔分类]CodeSmith (8)
- [随笔分类]其他 (4)
- [随笔分类]Ruby (4)
- [发布至博客园首页] (34)
- [网站分类]其他技术区 (3)
- [随笔分类]Ruby on Rails (2)
- [网站分类].NET新手区 (33)
- [随笔分类]TDD (1)
- [随笔分类]不谈技术 (2)
- [网站分类]非技术区 (7)
最新评论
-
yicone:
You make a mistake when paste t ...
WCF步步为营(一):简单示例 -
jinweijie:
你好,这个实现不错,但是在用了scriptmanager以后就 ...
在服务器端保存ViewState
本文参考了http://stephenwalther.com/blog/的内容。
今天需要对ASP.NET MVC的Controller进行测试,我们都知道当我们在测试工程里new一个controller时,这个controller里的httpcontext是空的,也就是session,cookie, form等都是空。
方法一:Mock controller的HttpContext, 暂时失败
那么我们如何对controller进行测试呢,我首先想到的是mock一个httpcontext,这里我用的是Rhino Mocks
public static class MvcMockHelpers
{
public static HttpContextBase FakeHttpContext(this MockRepository mocks)
{
HttpContextBase context = mocks.PartialMock<HttpContextBase>();
HttpRequestBase request = mocks.PartialMock<HttpRequestBase>();
HttpResponseBase response = mocks.PartialMock<HttpResponseBase>();
HttpSessionStateBase session = mocks.PartialMock<HttpSessionStateBase>();
HttpServerUtilityBase server = mocks.PartialMock<HttpServerUtilityBase>();
SetupResult.For(context.Request).Return(request);
SetupResult.For(context.Response).Return(response);
SetupResult.For(context.Session).Return(session);
SetupResult.For(context.Server).Return(server);
mocks.Replay(context);
return context;
}
public static HttpContextBase FakeHttpContext(this MockRepository mocks, string url)
{
HttpContextBase context = FakeHttpContext(mocks);
context.Request.SetupRequestUrl(url);
return context;
}
public static void SetFakeControllerContext(this MockRepository mocks, Controller controller)
{
var httpContext = mocks.FakeHttpContext();
ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller);
controller.ControllerContext = context;
}
下面我们建立一个ASP.NET MVC工程
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
namespace MVCTest.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult TestSession()
{
Session["name"] = "Jack Wang";
ViewData["Title"] = "Home Page";
ViewData["Message"] = "Welcome to ASP.NET MVC!";
if (Session["CurrentCulture"] != null)
{
ViewData["CurrentCulture"] = Session["CurrentCulture"];
}
return View();
}
public ActionResult TestForm()
{
ViewData["Name"] = Request.Form["Name"];
ViewData["Age"] = Request.Form["Age"];
ViewData["count"] = Request.Form.Count;
return View();
}
public ActionResult TestLogin()
{
if (User.Identity.IsAuthenticated)
{
ViewData["userName"] = User.Identity.Name;
return View("Admin");
}
else
{
return RedirectToAction("Index");
}
}
public ActionResult Admin()
{
if (User.IsInRole("Admin"))
{
return View("Admin");
}
else
{
return RedirectToAction("Index");
}
}
public ViewResult Details()
{
ViewData["PageSize"] = Request.QueryString["PageSize"];
ViewData["CurrentPage"] = Request.QueryString["CurrentPage"];
ViewData["count"] = Request.QueryString.Count;
return View();
}
public ViewResult TestCookie()
{
ViewData["key"] = Request.Cookies["key"].Value;
return View();
}
}
}
测试代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MVCTest;
using MVCTest.Controllers;
using MvcFakes;
using System.Web.SessionState;
using System.Web;
using System.Collections.Specialized;
using Rhino.Mocks;
namespace MVCTest.Tests.Controllers
{
/// <summary>
/// Summary description for HomeControllerTestByMock
/// </summary>
[TestClass]
public class HomeControllerTestByMock
{
public HomeControllerTestByMock()
{
//
// TODO: Add constructor logic here
//
}
private MockRepository mocks;
[TestInitialize]
public void Setup()
{
mocks = new MockRepository();
}
[TestMethod]
public void TestSession()
{
// Arrange
HomeController controller = new HomeController();
mocks.SetFakeControllerContext(controller);
controller.Session.Add("name", "Jack Wang");
SetupResult.For(controller.Session["CurrentCulture"]).Return("zh-CN");
mocks.ReplayAll();
// Act
ViewResult result = controller.TestSession() as ViewResult;
// Assert
ViewDataDictionary viewData = result.ViewData;
Assert.AreEqual("Home Page", viewData["Title"]);
Assert.AreEqual("Welcome to ASP.NET MVC!", viewData["Message"]);
Assert.AreEqual(controller.Session["name"], "Jack Wang");
Assert.AreEqual("zh-CN", viewData["CurrentCulture"]);
}
}
}
运行,测试
从错误信息可以看到是因为代码里Session["name"] = "Jack Wang"出错
本人排查很久,只知道mock的controllercontext的Session里没有这个Key,但现在还没有找到如何解决,哪位高人能帮吗解决?
二,自己写个模拟的Fake类,测试通过
既然这种方法不行,我们只能换一种方法,还好controller的ControllerContext可以赋值,这样我们就通过继承ControllerContext来Fake
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.SessionState;
namespace MvcFakes
{
public class FakeHttpSessionState : HttpSessionStateBase
{
private readonly SessionStateItemCollection _sessionItems;
public FakeHttpSessionState(SessionStateItemCollection sessionItems)
{
_sessionItems = sessionItems;
}
public override void Add(string name, object value)
{
_sessionItems[name] = value;
}
public override int Count
{
get
{
return _sessionItems.Count;
}
}
public override IEnumerator GetEnumerator()
{
return _sessionItems.GetEnumerator();
}
public override NameObjectCollectionBase.KeysCollection Keys
{
get
{
return _sessionItems.Keys;
}
}
public override object this[string name]
{
get
{
return _sessionItems[name];
}
set
{
_sessionItems[name] = value;
}
}
public override object this[int index]
{
get
{
return _sessionItems[index];
}
set
{
_sessionItems[index] = value;
}
}
public override void Remove(string name)
{
_sessionItems.Remove(name);
}
}
}
using System;
using System.Collections.Specialized;
using System.Web;
namespace MvcFakes
{
public class FakeHttpRequest : HttpRequestBase
{
private readonly NameValueCollection _formParams;
private readonly NameValueCollection _queryStringParams;
private readonly HttpCookieCollection _cookies;
public FakeHttpRequest(NameValueCollection formParams, NameValueCollection queryStringParams, HttpCookieCollection cookies)
{
_formParams = formParams;
_queryStringParams = queryStringParams;
_cookies = cookies;
}
public override NameValueCollection Form
{
get
{
return _formParams;
}
}
public override NameValueCollection QueryString
{
get
{
return _queryStringParams;
}
}
public override HttpCookieCollection Cookies
{
get
{
return _cookies;
}
}
}
}
using System;
using System.Security.Principal;
namespace MvcFakes
{
public class FakeIdentity : IIdentity
{
private readonly string _name;
public FakeIdentity(string userName)
{
_name = userName;
}
public string AuthenticationType
{
get { throw new System.NotImplementedException(); }
}
public bool IsAuthenticated
{
get { return !String.IsNullOrEmpty(_name); }
}
public string Name
{
get { return _name; }
}
}
}
using System;
using System.Linq;
using System.Security.Principal;
namespace MvcFakes
{
public class FakePrincipal : IPrincipal
{
private readonly IIdentity _identity;
private readonly string[] _roles;
public FakePrincipal(IIdentity identity, string[] roles)
{
_identity = identity;
_roles = roles;
}
public IIdentity Identity
{
get { return _identity; }
}
public bool IsInRole(string role)
{
if (_roles == null)
return false;
return _roles.Contains(role);
}
}
}
using System;
using System.Collections.Specialized;
using System.Security.Principal;
using System.Web;
using System.Web.SessionState;
namespace MvcFakes
{
public class FakeHttpContext : HttpContextBase
{
private readonly FakePrincipal _principal;
private readonly NameValueCollection _formParams;
private readonly NameValueCollection _queryStringParams;
private readonly HttpCookieCollection _cookies;
private readonly SessionStateItemCollection _sessionItems;
public FakeHttpContext(FakePrincipal principal, NameValueCollection formParams, NameValueCollection queryStringParams, HttpCookieCollection cookies, SessionStateItemCollection sessionItems )
{
_principal = principal;
_formParams = formParams;
_queryStringParams = queryStringParams;
_cookies = cookies;
_sessionItems = sessionItems;
}
public override HttpRequestBase Request
{
get
{
return new FakeHttpRequest(_formParams, _queryStringParams, _cookies);
}
}
public override IPrincipal User
{
get
{
return _principal;
}
set
{
throw new System.NotImplementedException();
}
}
public override HttpSessionStateBase Session
{
get
{
return new FakeHttpSessionState(_sessionItems);
}
}
}
}
using System;
using System.Collections.Specialized;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.SessionState;
namespace MvcFakes
{
public class FakeControllerContext : ControllerContext
{
public FakeControllerContext(ControllerBase controller)
: this(controller, null, null, null, null, null, null)
{
}
public FakeControllerContext(ControllerBase controller, HttpCookieCollection cookies)
: this(controller, null, null, null, null, cookies, null)
{
}
public FakeControllerContext(ControllerBase controller, SessionStateItemCollection sessionItems)
: this(controller, null, null, null, null, null, sessionItems)
{
}
public FakeControllerContext(ControllerBase controller, NameValueCollection formParams)
: this(controller, null, null, formParams, null, null, null)
{
}
public FakeControllerContext(ControllerBase controller, NameValueCollection formParams, NameValueCollection queryStringParams)
: this(controller, null, null, formParams, queryStringParams, null, null)
{
}
public FakeControllerContext(ControllerBase controller, string userName)
: this(controller, userName, null, null, null, null, null)
{
}
public FakeControllerContext(ControllerBase controller, string userName, string[] roles)
: this(controller, userName, roles, null, null, null, null)
{
}
public FakeControllerContext
(
ControllerBase controller,
string userName,
string[] roles,
NameValueCollection formParams,
NameValueCollection queryStringParams,
HttpCookieCollection cookies,
SessionStateItemCollection sessionItems
)
: base(new FakeHttpContext(new FakePrincipal(new FakeIdentity(userName), roles), formParams, queryStringParams, cookies, sessionItems),
new RouteData(), controller)
{ }
}
}
下面是测试类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MVCTest;
using MVCTest.Controllers;
using MvcFakes;
using System.Web.SessionState;
using System.Web;
using System.Collections.Specialized;
namespace MVCTest.Tests.Controllers
{
/// <summary>
/// Summary description for HomeControllerTest
/// </summary>
[TestClass]
public class HomeControllerTest
{
[TestMethod]
public void TestSession()
{
// Arrange
HomeController controller = new HomeController();
var sessionItems = new SessionStateItemCollection();
sessionItems["CurrentCulture"] = "zh-CN";
controller.ControllerContext = new FakeControllerContext(controller, sessionItems);
// Act
ViewResult result = controller.TestSession() as ViewResult;
// Assert
ViewDataDictionary viewData = result.ViewData;
Assert.AreEqual("Home Page", viewData["Title"]);
Assert.AreEqual("Welcome to ASP.NET MVC!", viewData["Message"]);
Assert.AreEqual(sessionItems["name"], "Jack Wang");
Assert.AreEqual("zh-CN", viewData["CurrentCulture"]);
}
[TestMethod]
public void TestFakeFormParams()
{
var controller = new HomeController();
var formParams = new NameValueCollection { { "Name", "Jack" }, { "Age", "28" } };
controller.ControllerContext = new FakeControllerContext(controller, formParams);
var result = controller.TestForm() as ViewResult;
Assert.AreEqual("Jack", result.ViewData["Name"]);
Assert.AreEqual("28", result.ViewData["Age"]);
Assert.AreEqual(formParams.Count, result.ViewData["count"]);
}
[TestMethod]
public void TestFakeQueryStringParams()
{
var controller = new HomeController();
var queryStringParams = new NameValueCollection { { "PageSize", "10" }, { "CurrentPage", "5" } };
controller.ControllerContext = new FakeControllerContext(controller, null, queryStringParams);
var result = controller.Details() as ViewResult;
Assert.AreEqual("10", result.ViewData["PageSize"]);
Assert.AreEqual("5", result.ViewData["CurrentPage"]);
Assert.AreEqual(queryStringParams.Count, result.ViewData["count"]);
}
[TestMethod]
public void TestFakeUser()
{
var controller = new HomeController();
controller.ControllerContext = new FakeControllerContext(controller, "Jack Wang");
var result = controller.TestLogin() as ActionResult;
Assert.IsInstanceOfType(result, typeof(ViewResult));
ViewDataDictionary viewData = ((ViewResult)result).ViewData;
Assert.AreEqual("Jack Wang", viewData["userName"]);
controller.ControllerContext = new FakeControllerContext(controller);
result = controller.TestLogin() as ActionResult;
Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
}
[TestMethod]
public void TestFakeUserRoles()
{
var controller = new HomeController();
controller.ControllerContext = new FakeControllerContext(controller, "Jack Wang", new string[] { "Admin" });
var result = controller.Admin() as ActionResult;
Assert.IsInstanceOfType(result, typeof(ViewResult));
controller.ControllerContext = new FakeControllerContext(controller);
result = controller.Admin() as ActionResult;
Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
}
[TestMethod]
public void TestCookies()
{
var controller = new HomeController();
var cookies = new HttpCookieCollection();
cookies.Add(new HttpCookie("key", "a"));
controller.ControllerContext = new FakeControllerContext(controller, cookies);
var result = controller.TestCookie() as ViewResult;
Assert.AreEqual("a", result.ViewData["key"]);
}
}
}
测试完全通过
总结: 个人感觉ASP.NET MVC的测试是很不友好的,和ruby on rails相比,在测试这一块还有很大的距离,希望正式版里这一块能够加强
王德水 写于2008-01-05 00:30分
发表评论
-
ASP.NET MVC源码现在可以下载了(翻译)
2008-03-22 09:44 941上个月我在blog里介绍了ASP.NET MVC Roadm ... -
ASP.NET MVC+LINQ开发一个图书销售站点
2008-03-29 17:12 1324园子里已经有很多人讲解了其理论知识,网上也有不少示例,但是很多 ... -
Linq to SQL Dynamic 动态查询
2008-04-01 15:09 1053在开发中我们常需要使用动态的条件来组合查询,scotte博客里 ... -
使用ASP.NET 3.5 Extensions管理浏览器历史:使用服务器端
2008-04-08 13:15 620我们知道当我们使用ASP.NET AJAX的一些方便的服务端控 ... -
客户比产品更重要
2008-04-12 15:49 659发现博客园里99%都是技术文章,很少有管理的经验分享 ... -
WPF 全球化和本地化(图解)
2008-04-12 16:15 826当您将自己的产品限制为只能通过一种语言使用时,您便将潜在的客户 ... -
项目经理如何参与任务管理
2008-04-14 17:55 678每个项目经理可能都会 ... -
.NET环境下每日集成
2008-04-24 17:36 1386本系列主要介绍了.Net环境下如何使用CruiseContro ... -
项目经理虚拟管理客户
2008-05-28 11:26 559项目经理做项目时经常 ... -
从中国男足看项目管理
2008-06-16 11:39 431国足1:2 不敌伊拉克后,彻底无缘本届世界杯,我想比赛时和赛后 ... -
敏捷的 "道"
2008-11-19 14:10 508本文摘要 敏捷的路上 ... -
在服务器端保存ViewState
2008-11-20 16:51 5741.比较 Asp.net 的一个强大的功能就是ViewStat ... -
TDD实验2:使用VSTS 的单元测试功能
2008-12-10 08:25 797我们要实现的功能是,发工资时自动向我们发送邮件,如果工资少于1 ... -
TDD Tip:方法内部New出来的对象如何Mock
2008-12-16 00:27 1243解决的问题:方法内部new的对象在测试时希望能够用mock对象 ... -
Web测试:Selenium使用
2008-12-23 10:49 1621<style> .confluenceTable ... -
谈软件协作:君子和而不同,小人同而不和
2008-12-31 18:39 705我们知道现在的软件开 ... -
如何使ASP.NET MVC Controller易测试呢?
2009-01-05 23:25 983昨天那篇文章如何进行ASP.NET MVC 的测试,虽然通过自 ... -
ASP.NET MVC AJAX的调用
2009-01-10 08:21 3767在ASP.NET MVC beta中我们可以使用Ajax.Be ... -
IIS7 配置ASP.NET 2.0, WCF, ASP.NET MVC
2009-01-16 17:50 4634ASP.NET 2.0 部署 1.首先打开win7 的特性,路 ... -
一步一步学Ruby(一): Ruby介绍
2009-01-21 00:16 792文章摘要 Ruby是如何来的 准备 ...
相关推荐
在ASP.NET MVC 5中,这些组件通过接口和依赖注入实现松耦合,增强了代码的可测试性和可维护性。 **ASP.NET MVC 5 的新特性** 1. **身份验证和授权** - ASP.NET MVC 5 引入了新的身份验证系统,基于Owin和Katana...
ASP.NET MVC4 CMS可能使用ASP.NET Identity进行用户认证和授权。这包括注册、登录、密码重置等功能,并且可以集成OAuth、OpenID Connect等外部身份验证服务。 **模块化和插件架构**: 为了保持系统的可扩展性,CMS...
学习ASP.NET MVC5,开发者可以掌握Web应用程序的高级开发技巧,包括如何组织项目结构、如何处理用户输入、如何进行数据库操作、如何实现用户认证和授权,以及如何调试和测试代码。"J.T.ASP.NET MVC 5.pdf"这个文件很...
- **测试驱动开发(Test-Driven Development, TDD)**:ASP.NET MVC鼓励TDD,可以使用诸如MSTest、NUnit或xUnit等测试框架编写单元测试,确保代码质量。 - ** Areas(区域)**:对于大型项目,ASP.NET MVC提供区域...
Asp.Net MVC支持单元测试,你可以为控制器、模型和业务逻辑编写测试用例,确保代码质量。这得益于MVC架构的松耦合特性,使得测试变得更加容易。 错误处理和异常过滤器(Exception Filters)是Asp.Net MVC中的重要...
ASP.NET MVC5 是微软开发的一款用于构建Web应用程序的框架,它结合了模型-视图-控制器(MVC)设计模式、ASP.NET Web Forms组件以及Web API功能,为开发者提供了更灵活、可测试的Web开发解决方案。这本书《ASP.NET ...
ASP.NET MVC(Model-View-Controller)是一种轻量级、基于组件的Web应用程序架构,它由微软开发并应用于.NET Framework中,为开发者提供了构建可测试、灵活且易于维护的Web应用的强大工具。本项目实例是针对初学者...
10. **单元测试(Unit Testing)**: ASP.NET MVC项目易于编写单元测试,因为控制器动作方法是无状态的。可以使用 MSTest, NUnit 或 xUnit 等测试框架进行测试。 这个压缩包中的项目文件可能涵盖了以上概念的实际...
6. **测试(Testing)**:由于MVC架构的分层特性,ASP.NET MVC项目易于编写单元测试和集成测试。开发者可以使用如NUnit、Moq或xUnit等测试框架来确保代码质量。 7. **Oxite项目**:在提供的文件列表中,"Oxite"可能...
10. **测试驱动开发**:ASP.NET MVC4鼓励测试驱动开发,提供了单元测试和集成测试的支持。 学习ASP.NET MVC4,你需要理解MVC模式的基本概念,掌握控制器、视图和模型的创建及交互,同时熟悉使用Razor视图引擎编写...
### AngularJS 开发 ASP.NET MVC #### 知识点概览 - **AngularJS与ASP.NET MVC结合的优势** - **AngularJS的特点与优势** - **AngularJS的基本概念(如数据绑定、指令等)** - **如何在ASP.NET MVC项目中引入...
ASP.NET MVC4是一种基于Microsoft .NET Framework的开源Web应用程序框架,设计用于构建可维护性和测试性的动态网站。这个"ASP.NET MVC4开发指南"提供了一套全面的学习资源,旨在帮助开发者掌握这一强大的Web开发技术...
asp.net MVC5提供了强类型、声明式、测试驱动的开发环境,而Easyui则简化了前端界面的复杂性,实现了前后端的良好分离。 在【压缩包子文件的文件名称列表】"RookeyFrame-v1.0"中,我们可以推测这是框架的初始版本,...
ASP.NET MVC4是一种基于微软.NET Framework的开源web应用程序框架,专为构建可维护性和测试性的动态网站而设计。它结合了MVC(Model-View-Controller)设计模式、ASP.NET的功能性和HTML5的新特性,提供了高效且灵活...
7. **单元测试与TDD**:ASP.NET MVC 5 支持测试驱动开发(TDD),其设计使得应用程序更易于进行单元测试,确保代码质量。 8. **Bootstrap与响应式设计**:很多ASP.NET MVC 5模板集成了Bootstrap框架,提供了一套...
ASP.NET MVC4.0是微软开发的一个开源框架,用于构建高度可测试、可维护的Web应用程序。这个框架结合了ASP.NET Web Forms和ASP.NET AJAX的功能,同时引入了Model-View-Controller(MVC)设计模式,使开发者能够更加...
ASP.NET MVC 2 是微软开发的一个用于构建动态网站的开源框架,它基于Model-View-Controller(MVC)设计模式,提供了清晰的架构,有助于分离关注点,提高代码的可测试性和可维护性。本教程将带你深入了解如何利用ASP...
ASP.NET MVC5高级编程(第5版.NET开发经典名著)作为Microsoft备受欢迎的MVC技术的最新版本,MVC 5是一个成熟的Web应用程序框架,支持快速的、TDD友好的开发。MVC允许开发人员创建动态的、数据驱动的网站。这样的...
10. **测试**:ASP.NET MVC4支持单元测试和集成测试,可以通过MSTest、NUnit或xUnit等测试框架编写测试用例,确保代码质量。 综上所述,使用VS2010和ASP.NET MVC4,结合SQL2008数据库,我们可以构建出功能强大、...
ASP.NET MVC(Model-View-Controller)是一种基于微软.NET Framework的Web应用程序开发框架,它为构建可维护性和测试性更强的Web应用提供了强大的支持。在本"ASP.NET MVC开发实战超完整源码"中,我们可以深入理解并...