I am trying the following, but I am getting : Object reference not set to an instance of an object.
HttpContextBase mockContext = MockRepository.GenerateMock<HttpContextBase>();
mockContext.Expect(c => c.Server.HtmlEncode("")).IgnoreArguments().Return("");
mockContext.Expect(c => c.Server.HtmlDecode("")).Return("");
controller.ControllerContext =
new ControllerContext(mockContext, new RouteData(), controller);
Matin,
Thanks. That was enough to point me in the right direction provided here:
var mockContext = MockRepository.GenerateMock<HttpContextBase>();
var mockServer = MockRepository.GenerateMock<HttpServerUtilityBase>();
mockServer.Expect(s => s.HtmlEncode(""))
.IgnoreArguments()
.Repeat.AtLeastOnce()
.Return("");
mockContext.Expect(c => c.Server)
.IgnoreArguments()
.Repeat.AtLeastOnce()
.Return(mockServer);
controller.ControllerContext =
new ControllerContext(mockContext, new RouteData(), controller);
Pure guess here:
var mockServer = MockRepository.GenerateMock<HttpServerUtilityBase>();
mockServer.Expect(x => x.HtmlEncode("")).IgnoreArguments().Return("");
Related
I'm trying to run unit tests for a project which is reliant on the web instance as it uses integrated windows authentication to verify the current user. When I run the tests it doesn't fire up the web instance, which is expected, but I need it to in order for any tests to succeed really. Anyone have any idea of how to do this?
Okay, I got this working in the end. You have to mock HttpContextBase (which is preferential over HttpContext I hear) and then set up your IPrincipal which is returned from the mock object. I'll give the full code listing so you get the idea:
[TestInitialize]
public void SetUp()
{
userRepositoryMock = new Mock<IUserRepository>();
controller = new AccountController(userRepositoryMock.Object);
httpContextMock = new Mock<HttpContextBase>();
IPrincipal fakeUser = new GenericPrincipal(new GenericIdentity("johnsmith#johns4232mith.com", "Forms"), null);
httpContextMock.Setup(x => x.User).Returns(fakeUser);
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();
var identity = new Mock<IIdentity>();
request.Setup(req => req.ApplicationPath).Returns("~/");
request.Setup(req => req.AppRelativeCurrentExecutionFilePath).Returns("~/");
request.Setup(req => req.PathInfo).Returns(string.Empty);
response.Setup(res => res.ApplyAppPathModifier(It.IsAny<string>()))
.Returns((string virtualPath) => virtualPath);
identity.SetupGet(ident => ident.IsAuthenticated).Returns(true);
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);
context.Setup(ctx => ctx.User).Returns(fakeUser);
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
}
I am working with a faked HttpContext (code provided in the end) and probably I am missing something because I can't access TempData collection (forth line of SetFakeControllerContext method). Every time I try I get this error message:
'controller.TempData' threw an exception of type 'System.AccessViolationException'
The code that calls FakeHttpContext is:
public static void SetFakeControllerContext(this Controller controller)
{
HttpContextBase httpContext = FakeHttpContext(string.Empty);
var context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller);
controller.ControllerContext = context;
controller.TempData = new TempDataDictionary(); //This is not necessary! It was just a test!!!!
}
Does anybody know what I am doing wrong?
public static HttpContextBase FakeHttpContext(string username){
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();
var user = new Mock<IPrincipal>();
var identity = new Mock<IIdentity>();
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);
context.Setup(ctx => ctx.User).Returns(user.Object);
user.Setup(ctx => ctx.Identity).Returns(identity.Object);
if (!string.IsNullOrEmpty(username))
{
identity.Setup(id => id.IsAuthenticated).Returns(true);
identity.Setup(id => id.Name).Returns(username);
}
else
{
identity.Setup(id => id.IsAuthenticated).Returns(false);
identity.Setup(id => id.Name).Returns(string.Empty);
}
context.Setup(ctx => ctx.Response.Cache).Returns(CreateCachePolicy());
return context.Object;
}
P.s.: I am using Moq
UPDATE:
OMG!! I CAN'T BELIEVE IT! More than 2 hours to figure out that the problem was a reference to the wrong MVC dll. I was referencing System.Web.Mvc 2.0 for my main app but System.Web.Mvc 1.0 in another project. Sorry about this!
The problem's definitely somewhere else. You don't even need to initialize the TempData property to a new dictionary in your unit test. The following program works fine:
public class HomeController: Controller
{
public ActionResult Index()
{
TempData["foo"] = "bar";
return View();
}
}
class Program
{
static void Main()
{
var controller = new HomeController();
controller.Index();
Console.WriteLine(controller.TempData["foo"]);
}
}
I'm using this helper method to turn my PartialViewResult into string and returning it as Json - http://www.atlanticbt.com/blog/asp-net-mvc-using-ajax-json-and-partialviews/
My problem is that I'm using Moq to mock the controller, and whenever I run unit test that uses this RenderPartialViewToString() method, I got the "Object reference not set to an instance of an object." error on ControllerContext.
private ProgramsController GetController()
{
var mockHttpContext = new Mock<ControllerContext>();
mockHttpContext.SetupGet(p => p.HttpContext.User.Identity.Name).Returns("test");
mockHttpContext.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);
// Mock Repositories
var mockOrganizationRepository = new MockOrganizationRepository(MockData.MockOrganizationsData());
var mockIRenderPartial = new BaseController();
var controller = new ProgramsController(mockOrganizationRepository, mockIRenderPartial);
controller.ControllerContext = mockHttpContext.Object;
return controller;
}
This returns a proxy controller, and maybe it's the reason why I got that error. Any idea how to unit testing this?
Thank you very much.
try this:
public static void SetContext(this Controller controller)
{
var httpContextBase = new Mock<HttpContextBase>();
var httpRequestBase = new Mock<HttpRequestBase>();
var respone = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var routes = new RouteCollection();
RouteConfigurator.RegisterRoutesTo(routes);
httpContextBase.Setup(x => x.Response).Returns(respone.Object);
httpContextBase.Setup(x => x.Request).Returns(httpRequestBase.Object);
httpContextBase.Setup(x => x.Session).Returns(session.Object);
session.Setup(x => x["somesessionkey"]).Returns("value");
httpRequestBase.Setup(x => x.Form).Returns(new NameValueCollection());
controller.ControllerContext = new ControllerContext(httpContextBase.Object, new RouteData(), controller);
controller.Url = new UrlHelper(new RequestContext(controller.HttpContext, new RouteData()), routes);
}
Specifically, how can I pass the static method Request.IsAjaxRequest()?
I get the exception 'System.ArgumentNullException' when I try to test the following code:
if (Request.IsAjaxRequest())
{
return Json(data);
}
return View(data2);
I'm using Moq. Thanks for any help.
You need mocking Request and Request.Headers to work with Request.IsAjaxRequest():
var request = new Mock<HttpRequestBase>();
request.SetupGet(x => x.Headers).Returns(new System.Net.WebHeaderCollection {
{"X-Requested-With", "XMLHttpRequest"}
});
var context = new Mock<HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);
var controller = new YourController();
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
One of my controllers actions, one that is being called in an Ajax request, is returning an URL to the client side so it can do a redirection. I'm using Url.RouteUrl(..) and during my unit tests this fails since the Controller.Url parameter is not pre-filled.
I tried a lot of things, among others attempting to stub UrlHelper (which failed), manually creating a UrlHelper with a RequestContext that has a stubbed HttpContextBase (which failed on a RouteCollection.GetUrlWithApplicationPath call).
I have searched Google but found virtually nothing on the subject. Am I doing something incredibly stupid using Url.RouteUrl in my Controller action? Is there an easier way?
To make it even worse, I'd like to be able to test the returned URL in my unit test - in fact I'm only interested in knowing it's redirecting to the right route, but since I'm returning an URL instead of a route, I would like to control the URL that is resolved (eg. by using a stubbed RouteCollection) - but I'll be happy to get my test passing to begin with.
Here is one of my tests (xUnit + Moq) just for similar case (using Url.RouteUrl in controller)
var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());
var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
response.Setup(x => x.ApplyAppPathModifier("/post1")).Returns("http://localhost/post1");
var context = new Mock<HttpContextBase>(MockBehavior.Strict);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
var controller = new LinkbackController(dbF.Object);
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);
A modified implementation from eu-ge-ne. This one returns a generated link based on the routes defined in the application. eu-ge-ne's example always returned a fixed response. The approach below will allow you to test that the correct action/controller and route information is being passed into the UrlHelper - which is what you want if you are testing call to the UrlHelper.
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);
request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new NameValueCollection());
response.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(x => x);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
var helper = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);
Building off the answer by #eu-ge-ne which helped me a great deal:
I had an ActionResult that did a redirect as well as had an UpdateModel call with a FormCollection parameter. For the UpdateModel() to work I had to add this to my Mocked HttpRequestBase:
FormCollection collection = new FormCollection();
collection["KeyName"] = "KeyValue";
request.Setup(x => x.Form).Returns(collection);
request.Setup(x => x.QueryString).Returns(new NameValueCollection());
To test that the redirected URL was correct, you can do the following:
RedirectResult result = controller.ActionName(modelToSubmit, collection) as RedirectResult;
Assert.AreEqual("/Expected/URL", result.Url);