模拟和HttpContextBase.get_User()

我想模拟HttpContext的User属性。 我正在使用Scott Hanselmans MVCHelper类和RhinoMocks。

我有一个包含代码的unit testing,如下所示:

MockIdentity fakeId = new MockIdentity("TEST_USER", "Windows", true); MockPrincipal fakeUser = new MockPrincipal(null, fakeId); using (mocks.Record()) { Expect.Call(fakeHttpContext.User).Return(fakeUser); } 

我的MockIdentity和MockPrincipal类分别是符合IIdentity和IPrincipal的模拟。

运行报告的unit testing时出错:

System.NotImplementedException:未实现方法或操作。 在System.Web.HttpContextBase.get_User()

当我尝试设置User属性的期望时,就会发生这种情况。

我知道httpContextBase有一个没有实现的getter和setter但我认为Rhino会在mocking时处理这个问题。

这是否意味着我必须从HttpContextbase派生并覆盖我的mock对象的属性。 这看起来很奇怪。

其他用户遇到过这个问题,并在此处报告: http : //www.mail-archive.com/rhinomocks@googlegroups.com/msg00546.html

要模拟用户属性,可以执行以下操作:

 var httpContext = MockRepository.GenerateStub(); httpContext.Stub(x=>x.User).Return(yourFakePrincipalHere); var controllerContext = new ControllerContext(httpContext, ....); var controller = new HomeController(); controller.ControllerContext = controllerContext; 

(这使用新的RM 3.5 api,如果你正在进行记录/重播,那么:

 using(mocks.Record) { _httpContext = _mocks.DynamicMock(); SetupResult.For(_httpContext.User).Return(...); } using(mocks.PlayBack()) { .... } 

我遇到了几乎相同的问题并搬到了Moq。

这是我在我的应用中使用的自定义助手:

 public static class MvcMockHelpers { public static HttpContextBase FakeHttpContext() { var context = new Mock(); var request = new Mock(); var response = new Mock(); var session = new Mock(); var server = new Mock(); context.Expect(ctx => ctx.Request).Returns(request.Object); context.Expect(ctx => ctx.Response).Returns(response.Object); context.Expect(ctx => ctx.Session).Returns(session.Object); context.Expect(ctx => ctx.Server).Returns(server.Object); var form = new NameValueCollection(); var querystring = new NameValueCollection(); var cookies = new HttpCookieCollection(); var user = new GenericPrincipal(new GenericIdentity("testuser"), new string[] { "Administrator" }); request.Expect(r => r.Cookies).Returns(cookies); request.Expect(r => r.Form).Returns(form); request.Expect(q => q.QueryString).Returns(querystring); response.Expect(r => r.Cookies).Returns(cookies); context.Expect(u => u.User).Returns(user); return context.Object; } public static HttpContextBase FakeHttpContext(string url) { HttpContextBase context = FakeHttpContext(); context.Request.SetupRequestUrl(url); return context; } public static void SetFakeControllerContext(this Controller controller) { var httpContext = FakeHttpContext(); ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller); controller.ControllerContext = context; } public static void SetFakeControllerContext(this Controller controller, RouteData routeData) { SetFakeControllerContext(controller, new Dictionary(), new HttpCookieCollection(), routeData); } public static void SetFakeControllerContext(this Controller controller, HttpCookieCollection requestCookies) { SetFakeControllerContext(controller,new Dictionary(),requestCookies, new RouteData()); } public static void SetFakeControllerContext(this Controller controller, Dictionary formValues) { SetFakeControllerContext(controller, formValues, new HttpCookieCollection(), new RouteData()); } public static void SetFakeControllerContext(this Controller controller, Dictionary formValues, HttpCookieCollection requestCookies, RouteData routeData) { var httpContext = FakeHttpContext(); foreach (string key in formValues.Keys) { httpContext.Request.Form.Add(key, formValues[key]); } foreach (string key in requestCookies.Keys) { httpContext.Request.Cookies.Add(requestCookies[key]); } ControllerContext context = new ControllerContext(new RequestContext(httpContext, routeData), controller); controller.ControllerContext = context; } public static void SetFakeControllerContextWithLogin(this Controller controller, string userName, string password, string returnUrl) { var httpContext = FakeHttpContext(); httpContext.Request.Form.Add("username", userName); httpContext.Request.Form.Add("password", password); httpContext.Request.QueryString.Add("ReturnUrl", returnUrl); ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller); controller.ControllerContext = context; } static string GetUrlFileName(string url) { if (url.Contains("?")) return url.Substring(0, url.IndexOf("?")); else return url; } static NameValueCollection GetQueryStringParameters(string url) { if (url.Contains("?")) { NameValueCollection parameters = new NameValueCollection(); string[] parts = url.Split("?".ToCharArray()); string[] keys = parts[1].Split("&".ToCharArray()); foreach (string key in keys) { string[] part = key.Split("=".ToCharArray()); parameters.Add(part[0], part[1]); } return parameters; } else { return null; } } public static void SetHttpMethodResult(this HttpRequestBase request, string httpMethod) { Mock.Get(request) .Expect(req => req.HttpMethod) .Returns(httpMethod); } public static void SetupRequestUrl(this HttpRequestBase request, string url) { if (url == null) throw new ArgumentNullException("url"); if (!url.StartsWith("~/")) throw new ArgumentException("Sorry, we expect a virtual url starting with \"~/\"."); var mock = Mock.Get(request); mock.Expect(req => req.QueryString) .Returns(GetQueryStringParameters(url)); mock.Expect(req => req.AppRelativeCurrentExecutionFilePath) .Returns(GetUrlFileName(url)); mock.Expect(req => req.PathInfo) .Returns(string.Empty); } 

[ 免责声明 :我在Typemock工作]

我知道这不是你所问的,但是看看上面的答案,我必须展示另一种方法来做你需要的 – 使用隔离器 :

 var fakeId = Isolate.Fake.Instance(); Isolate.WhenCalled(() => fakeId.AuthenticationType).WillReturn("Windows"); Isolate.WhenCalled(() => fakeId.Name).WillReturn("TEST_USER"); Isolate.WhenCalled(() => fakeId.IsAuthenticated).WillReturn(true); var fakePrincipal = Isolate.Fake.Instance(); Isolate.WhenCalled(() => fakePrincipal.Identity).WillReturn(fakeId); var fakeContext = Isolate.Fake.Instance(); Isolate.WhenCalled(() => fakeContext.User).WillReturn(fakePrincipal);