Microsoft.Web.Mvc.LinkBuilder.BuildUrlFromExpression failing when testing Asp.net MVC app
So I'm trying to unit-test a controller method. I'm using MSTest in VS 2010, and Moq 3.1
Test method:
[TestMethod]
public void TestAccountSignup()
{
var request = new Mock<HttpRequestBase>();
var context = new Mock<HttpContextBase>();
AccountController controller = new AccountController();
controller.ControllerContext = new System.Web.Mvc.ControllerContext(context.Object, new RouteData(), con开发者_开发知识库troller);
request.Setup(x => x.Cookies).Returns(new HttpCookieCollection());
context.Setup(x => x.Request).Returns(request.Object);
string username = StringHelper.GenerateRandomAlpha(10);
var res = controller.Register(username, "foozbaaa+" + username + "@example.com", null, true, "Testing!", null);
}
My controller method:
[CaptchaValidator]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(string userName, string email,string existingUsername, bool captchaValid, string heardAbout, string heardAboutOther)
{
//Loads of stuff here....
//cool - all registered
//This line gives the problem
return new RedirectResult(this.BuildUrlFromExpression<AccountController>(x => x.AccountCreated()));
}
The controller method works just fine when not unit testing.
When mocking and calling in this way, I get a System.Security.VerificationException on that last line:
Method Microsoft.Web.Mvc.LinkBuilder.BuildUrlFromExpression: type argument 'TController' violates the constraint of type parameter 'TController'.
Now clearly AccountController is of type TController, otherwise it wouldn't work when not unit-testing. It inherits from my BaseController, which inherits from the regular Controller.
I get the feeling this error is a red-herring, due to the mocking - any ideas why?
Many thanks.
This is because Futures uses a slightly different Controller type.
I'm not sure of the specifics but I encountered the same issue. Its either a futures Controller vs a MVC 2 Controller or MVC 1 Controller vs a MVC 2 controller.
See if fully qualifying the type name helps.
How about the following:
[HttpPost]
public ActionResult Register()
{
return this.RedirectToAction<AccountController>(x => x.AccountCreated());
}
RedirectToAction<T>
is an extension method to the Controller
class defined in Microsoft.Web.Mvc.ControllerExtensions
(part of ASP.NET MVC futures).
Now it's much easier to unit test. You don't even need to mock the context:
// arrange
var controller = new AccountController();
// act
var actual = controller.Register();
And if you use the excellent MvcContrib.TestHelper which I would strongly recommend you, the assert part of your unit test could look like this:
// assert
actual
.AssertActionRedirect()
.ToAction<AccountController>(x => x.AccountCreated());
精彩评论