在软件开发过程中,测试是一个不可或缺的环节。对于ASP.NET MVC应用来说,测试通常分为单元测试和集成测试。单元测试关注于单个组件的行为,而集成测试则关注于组件之间的交互。在某些情况下,如控制器的测试,单元测试相对容易实现;但对于模型绑定器等组件,单元测试则较为困难。此外,对于安全性相关的测试,单独测试单个代码片段可能没有太大意义。在这种情况下,需要进行集成测试。在ASP.NET MVC的上下文中,集成测试通常意味着使用浏览器自动化框架,如SeleniumRC、WatiN或轻量级测试自动化框架。这些工具可以自动化真实浏览器实例,但需要将测试的网站托管在Web服务器上,因此这种方式的测试需要较多的资源,并可能引入一系列问题和错误可能性。
为了使这些测试更加友好、资源需求更少、错误更少,找到了一篇博客文章:。这篇文章介绍了一个框架,可以在不需要任何浏览器或服务器的情况下,对ASP.NET MVC应用进行集成测试,但仍然在真实的(非模拟的)ASP.NET运行时环境中运行。可以参考上述文章,了解更多关于所谓的MvcIntegrationTestFramework的基本原理、各种可能性和技术细节,以及如何使用它的更多示例。
为了将这个框架更紧密地集成到Gallio/MbUnit环境中,发现编写一个自定义测试夹具的基类很有用,它基本上是MvcIntegrationTestFramework的一个包装器。这样,就可以像下面这样对MVC应用进行测试(记住:不需要浏览器或服务器或其他任何东西,它就是可以工作...):
public void SimulateRequestToRootUrl()
{
RunSession(session =>
{
// 请求根URL
RequestResult result = session.ProcessRequest("~/");
// 关于创建请求的控制器的断言...
var controller = result.ActionExecutedContext.Controller as HomeController;
Assert.IsNotNull(controller);
// 关于ActionResult的断言...
var viewResult = (ViewResult)result.ActionExecutedContext.Result;
Assert.AreEqual("Index", viewResult.ViewName);
Assert.AreEqual("Welcome to ASP.NET MVC!", viewResult.ViewData["Message"]);
// 关于渲染的HTML的断言...
Assert.IsTrue(result.ResponseText.Contains("
...或者,测试登录/防伪造机制,如下所示:
[Test]
public void TryingToAccessSecuredPageWithoutLoggingInIsBeingRedirected()
{
RunSession(session =>
{
RequestResult result = session.ProcessRequest(SecuredUrl);
Assert.IsTrue(result.Response.IsRequestBeingRedirected);
});
}
[Test]
public void CanAccessSecuredPageAfterLoggingIn()
{
RunSession(session =>
{
// 首先重定向到登录页面并获取防伪造令牌
string loginRedirectUrl = session.ProcessRequest(SecuredUrl).Response.RedirectLocation;
string loginPageResponseText = session.ProcessRequest(loginRedirectUrl).ResponseText;
string antiForgeryToken = MvcUtils.ExtractAntiForgeryToken(loginPageResponseText);
// 使用用户凭据和验证令牌提交登录表单
var formData = new NameValueCollection
{
{"username", "thomas"},
{"password", "blah"},
{"__RequestVerificationToken", antiForgeryToken}
};
session.ProcessRequest(loginRedirectUrl, HttpVerbs.Post, formData);
// 现在,登录后再次访问受保护的页面...
RequestResult result = session.ProcessRequest(SecuredUrl);
// ...这次应该一切正常。
Assert.AreEqual("Hello thomas!", result.ResponseText);
});
}
上述代码是自解释的,认为。要使其工作,自定义测试夹具必须派生自MvcIntegrationFixture基类,该类只需要在构造函数中提供Web应用的基本目录:
public class MvcIntegrationFixture : MvcIntegrationFixtureBase
{
public MvcIntegrationFixture()
: base(Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory + "\\..\\..\\..\\MvcIntegrationFixtureDemo"))
{
// 测试放在这里...
}
}