ASP.NET MVC控制器单元测试
尝试在ASP.NET MVC 3 Web应用程序中执行一些控制器单元测试。
我的测试是这样的:
[TestMethod]
public void Ensure_CreateReviewHttpPostAction_RedirectsAppropriately()
{
// Arrange.
var newReview = CreateMockReview();
// Act.
var result = _controller.Create(newReview) as RedirectResult;
// Assert.
Assert.IsNotNull(result, "RedirectResult was not returned");
}
很简单。 基本上测试一个[HttpPost]
动作以确保它返回一个RedirectResult
(PRG模式)。 我没有使用RedirectToRouteResult
因为没有重载支持锚链接。 继续。
现在,我使用Moq来模拟Http上下文,包括服务器变量,控制器上下文,会话等等。一切进展顺利。
直到我在我的操作方法中找到了这一行:
return Redirect(Url.LandingPageWithAnchor(someObject.Uri, review.Uri);
LandingPageWithAnchor
是一个自定义HTML帮助程序:
public static string LandingPageWithAnchor(this UrlHelper helper, string uri1, string uri2)
{
const string urlFormat = "{0}#{1}";
return string.Format(urlFormat,
helper.RouteUrl("Landing_Page", new { uri = uri1}),
uri2);
}
基本上,我重定向到另一个页面,该页面是新内容的“着陆页”,并以新评论为主角。 凉。
现在,这个方法之前失败了,因为UrlHelper
为null。
所以我在嘲笑中这样做了:
controller.Url = new UrlHelper(fakeRequestContext);
它进一步得到了它,但现在它失败了,因为路由表不包含“Landing_Page”的定义。
所以我知道我需要嘲笑“某事”,但我不知道它是否是:
a)路线表
b)UrlHelper.RouteUrl方法
c)我写的UrlHelper.LandingPageWithAnchor扩展方法
任何人可以提供一些指导?
编辑
这个特定的路线是在一个区域 ,所以我尝试在我的单元测试中调用区域注册:
AreaRegistration.RegisterAllAreas();
但我得到一个InvalidOperationException
:
在应用程序的预启动初始化阶段不能调用此方法。
通过模拟HttpContext,RequestContext和ControllerContext来实现它,注册路由,然后用这些路由创建一个UrlHelper
。
有点像这样:
public static void SetFakeControllerContext(this Controller controller, HttpContextBase httpContextBase)
{
var httpContext = httpContextBase ?? FakeHttpContext().Object;
var requestContext = new RequestContext(httpContext, new RouteData());
var controllerContext = new ControllerContext(requestContext, controller);
MvcApplication.RegisterRoutes();
controller.ControllerContext = controllerContext;
controller.Url = new UrlHelper(requestContext, RouteTable.Routes);
}
FakeHttpContext()
是一个Moq帮助器,它可以创建所有模拟的东西,服务器变量,会话等。
UrlHelper
的构造函数将RouteCollection
作为第二个参数。 如果你有MVC为你创建的默认设置,那么我认为这应该适合你:
var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
controller.Url = new UrlHelper(fakeRequestContext, routes);
另一种方法是修改应用程序的启动方式,使测试和使用起来更容易一些。 如果你定义和界面如下所示:
public interface IMvcApplication
{
void RegisterRoutes(RouteCollection routes);
// Other startup operations
}
通过实施:
public class MyCustomApplication : IMvcApplication
{
public void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Your route registrations here
}
// Other startup operations
}
然后你可以像这样修改你的Global.asax
:
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
var app = new MyCustomApplication();
app.RegisterRoutes(RouteTable.Routes);
// Other startup calls
}
}
并且仍然可以灵活地注册您的路线进行测试。 像这样的东西:
private IMvcApplication _app;
private RouteCollection _routes;
[TestInitialize]
public void InitializeTests()
{
_app = new MyCustomApplication();
_routes = new RouteCollection();
_app.RegisterRoutes(_routes);
}
这同样可以用于区域注册。
private RouteCollection _routes;
private MyCustomAreaRegistration _area;
[TestInitialize]
public void InitTests()
{
_routes = new RouteCollection();
var context = new AreaRegistrationContext("MyCustomArea", _routes);
_area.RegisterArea(context);
}
因为这是一个测试,所以您的测试套件很可能不像您所期望的那样读取Global.asax。
为了解决这个问题,请执行@ataddeini建议的操作并创建一个路由集合。 在这个集合中添加一个新的路线,它看起来像......
var routes = new RouteCollection();
routes.Add(new Route("Landing_Page", new { /*pass route params*/}, null));
var helper = new UrlHelper(fakeRequestContext, routes);
链接地址: http://www.djcxy.com/p/57851.html