问题
I am new to MOQ, but am using it with NUnit for unit testing.
I have all parts of my controller mocked, except the following line which throws an 'Object not set to an instance of an object' error message.
Response.Cookies.Clear();
I have the following extension method to mock the controller context which works for everything else I have come accross so far (very much thanks to the good people on this forum).
public static int SetUpForTest(this System.Web.Mvc.Controller ctl, string username, TestingUtility.Roles role)
{
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(Moq.It.IsAny<String>())).Returns((String url) => url);
// response.SetupGet(x => x.Cookies).Returns(new HttpCookieCollection()); // This also failed to work
var context = new Mock<HttpContextBase>(MockBehavior.Strict);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
context.SetupGet(x => x.Response.Cookies).Returns(new HttpCookieCollection()); // still can't call the Clear() method
//
// Mock the controller context (using the objects mocked above)
//
var moqCtx = new Mock<ControllerContext>(context.Object, new RouteData(), ctl);
moqCtx.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(username);
moqCtx.SetupGet(p => p.HttpContext.User.Identity.IsAuthenticated).Returns(true);
if (!string.IsNullOrEmpty(role.ToString()))
moqCtx.Setup(p => p.HttpContext.User.IsInRole(role.ToString())).Returns(true);
//
// Pass the mocked ControllerContext and create UrlHelper for the controller and return
//
ctl.ControllerContext = moqCtx.Object;
ctl.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);
return 1;
}
As you can see above I have tried to mock the 'get' of the cookies collection, which does not help.
Also, the actual Clear() method cannot be mocked as it is not a virtual method.
Obviously I don't want to test that the cookies are being cleared, I just want to be able to ignore it in testing.
Thanks,
Greg
回答1:
This works for me when I do cookies.Clear()
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(Moq.It.IsAny<String>())).Returns((String url) => url);
// response.SetupGet(x => x.Cookies).Returns(new HttpCookieCollection()); // This also failed to work
var context = new Mock<HttpContextBase>(MockBehavior.Strict);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
context.SetupGet(x => x.Response.Cookies).Returns(new HttpCookieCollection()); // still can't call the Clear() method
context.SetupGet(p => p.User.Identity.Name).Returns("blah");
context.SetupGet(p => p.User.Identity.IsAuthenticated).Returns(true);
var rc = new RequestContext(context.Object, new RouteData());
controller.ControllerContext = new ControllerContext(rc, controller);
回答2:
(This is only half an answer, but was too big for the comment field ...)
Your mocking of new HttpCookieCollection()
is correct. This code works in separation:
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(Moq.It.IsAny<String>())).Returns((String url) => url);
// response.SetupGet(x => x.Cookies).Returns(new HttpCookieCollection()); // This also failed to work
var context = new Mock<HttpContextBase>(MockBehavior.Strict);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
context.SetupGet(x => x.Response.Cookies).Returns(new HttpCookieCollection()); // still can't call the Clear() method
// Here clearing the cookies works just fine:
var instance = context.Object;
instance.Response.Cookies.Clear();
So the error is not there, but somewhere else. What happens if you comment out the line with Response.Cookies.Clear()
from your code? Is everything else mocked correctly then? When you debug the test, can you see that the rest of the mock is as expected? I would be surprised if it was (but I have been surprised before...).
来源:https://stackoverflow.com/questions/18098585/moq-mocking-mvc-controllers-response-cookies-clear