C# 模拟和 HttpContextBase.get_User()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/677801/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mocking and HttpContextBase.get_User()
提问by Lewis
I want to mock the User property of an HttpContext. I'm using Scott Hanselmans MVCHelper class and RhinoMocks.
我想模拟 HttpContext 的 User 属性。我正在使用 Scott Hanselmans MVCHelper 类和 RhinoMocks。
I have a unit test that contains code, like this:
我有一个包含代码的单元测试,如下所示:
...
...
MockIdentity fakeId = new MockIdentity("TEST_USER", "Windows", true);
MockPrincipal fakeUser = new MockPrincipal(null, fakeId);
using (mocks.Record())
{
Expect.Call(fakeHttpContext.User).Return(fakeUser);
}
...
...
My MockIdentity and MockPrincipal classes are mocks conforming to IIdentity and IPrincipal, respectively.
我的 MockIdentity 和 MockPrincipal 类分别是符合 IIdentity 和 IPrincipal 的模拟。
I get an error when running the unit test that reports:
运行报告的单元测试时出现错误:
System.NotImplementedException : The method or operation is not implemented. at System.Web.HttpContextBase.get_User()
System.NotImplementedException :方法或操作未实现。在 System.Web.HttpContextBase.get_User()
This is happening when I'm trying to set the expectation for the User property.
当我尝试为 User 属性设置期望时,就会发生这种情况。
I understand that the httpContextBase has a getter and setter that aren't implemented but I thought that Rhino would handle this when mocking.
我知道 httpContextBase 有一个没有实现的 getter 和 setter,但我认为 Rhino 会在模拟时处理这个问题。
Does this mean that I have to derive from the HttpContextbase and override the property for my mock object. It seems odd.
这是否意味着我必须从 HttpContextbase 派生并覆盖我的模拟对象的属性。这似乎很奇怪。
Other users have had this issue and it's reported here: http://www.mail-archive.com/[email protected]/msg00546.html
其他用户也遇到过这个问题,并在此处报告:http: //www.mail-archive.com/[email protected]/msg00546.html
采纳答案by Ben Scheirman
To mock the user property, you can do this:
要模拟用户属性,您可以执行以下操作:
var httpContext = MockRepository.GenerateStub<HttpContextBase>();
httpContext.Stub(x=>x.User).Return(yourFakePrincipalHere);
var controllerContext = new ControllerContext(httpContext, ....);
var controller = new HomeController();
controller.ControllerContext = controllerContext;
(this uses the new RM 3.5 api, if you're doing it w/ record/replay then:
(这使用新的 RM 3.5 api,如果您使用记录/重播进行此操作,则:
using(mocks.Record)
{
_httpContext = _mocks.DynamicMock<HttpContextBase>();
SetupResult.For(_httpContext.User).Return(...);
}
using(mocks.PlayBack())
{
....
}
回答by Geo
I had nearly the same problem and moved to Moq.
我遇到了几乎相同的问题并搬到了 Moq。
This is the custom helper I uses in my apps:
这是我在我的应用程序中使用的自定义助手:
public static class MvcMockHelpers
{
public static HttpContextBase FakeHttpContext()
{
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.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<string, string>(), new HttpCookieCollection(), routeData);
}
public static void SetFakeControllerContext(this Controller controller, HttpCookieCollection requestCookies)
{
SetFakeControllerContext(controller,new Dictionary<string,string>(),requestCookies, new RouteData());
}
public static void SetFakeControllerContext(this Controller controller, Dictionary<string, string> formValues)
{
SetFakeControllerContext(controller, formValues, new HttpCookieCollection(), new RouteData());
}
public static void SetFakeControllerContext(this Controller controller,
Dictionary<string, string> 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);
}
回答by Dror Helper
[Dislaimer: I work at Typemock]
I know it's not what you've asked but looking at the answers above I have to show another way to do what you need - using Isolator:
我知道这不是你问的问题,但看看上面的答案,我必须展示另一种方法来做你需要的 - 使用Isolator:
var fakeId = Isolate.Fake.Instance<IIdentity>();
Isolate.WhenCalled(() => fakeId.AuthenticationType).WillReturn("Windows");
Isolate.WhenCalled(() => fakeId.Name).WillReturn("TEST_USER");
Isolate.WhenCalled(() => fakeId.IsAuthenticated).WillReturn(true);
var fakePrincipal = Isolate.Fake.Instance<IPrincipal>();
Isolate.WhenCalled(() => fakePrincipal.Identity).WillReturn(fakeId);
var fakeContext = Isolate.Fake.Instance<HttpContext>();
Isolate.WhenCalled(() => fakeContext.User).WillReturn(fakePrincipal);