测试 Init 方法中的模拟 HttpContext.Current
我正在尝试向我构建的 ASP.NET MVC 应用程序添加单元测试。在我的单元测试中,我使用以下代码:
[TestMethod]
public void IndexAction_Should_Return_View() {
var controller = new MembershipController();
controller.SetFakeControllerContext("TestUser");
...
}
使用以下帮助程序来模拟控制器上下文:
public static class FakeControllerContext {
public static HttpContextBase FakeHttpContext(string username) {
var context = new Mock<HttpContextBase>();
context.SetupGet(ctx => ctx.Request.IsAuthenticated).Returns(!string.IsNullOrEmpty(username));
if (!string.IsNullOrEmpty(username))
context.SetupGet(ctx => ctx.User.Identity).Returns(FakeIdentity.CreateIdentity(username));
return context.Object;
}
public static void SetFakeControllerContext(this Controller controller, string username = null) {
var httpContext = FakeHttpContext(username);
var context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller);
controller.ControllerContext = context;
}
}
该测试类继承自具有以下内容的基类:
[TestInitialize]
public void Init() {
...
}
在该方法内部,它调用一个库(我无法控制该库),该库尝试运行以下代码:
HttpContext.Current.User.Identity.IsAuthenticated
现在您可能可以看到问题了。我已经针对控制器设置了假的 HttpContext,但没有在此基本 Init 方法中设置。单元测试/模拟对我来说非常陌生,所以我想确保我做对了。我模拟 HttpContext 以便在我的控制器和 Init 方法中调用的任何库之间共享它的正确方法是什么。
I'm trying to add unit testing to an ASP.NET MVC application I have built. In my unit tests I use the following code:
[TestMethod]
public void IndexAction_Should_Return_View() {
var controller = new MembershipController();
controller.SetFakeControllerContext("TestUser");
...
}
With the following helpers to mock the controller context:
public static class FakeControllerContext {
public static HttpContextBase FakeHttpContext(string username) {
var context = new Mock<HttpContextBase>();
context.SetupGet(ctx => ctx.Request.IsAuthenticated).Returns(!string.IsNullOrEmpty(username));
if (!string.IsNullOrEmpty(username))
context.SetupGet(ctx => ctx.User.Identity).Returns(FakeIdentity.CreateIdentity(username));
return context.Object;
}
public static void SetFakeControllerContext(this Controller controller, string username = null) {
var httpContext = FakeHttpContext(username);
var context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller);
controller.ControllerContext = context;
}
}
This test class inherits from a base class which has the following:
[TestInitialize]
public void Init() {
...
}
Inside this method it calls a library (which i have no control over) which tries to run the following code:
HttpContext.Current.User.Identity.IsAuthenticated
Now you can probably see the problem. I have set the fake HttpContext against the controller but not in this base Init method. Unit testing / mocking is very new to me so I want to make sure I get this right. What is the correct way for me to Mock out the HttpContext so that it is shared across my controller and any libraries which are called in my Init method.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
HttpContext.Current
返回System.Web 的实例.HttpContext
,它不扩展System。 Web.HttpContextBase
。后来添加了 HttpContextBase 来解决 HttpContext 难以模拟的问题。这两个类基本上不相关(HttpContextWrapper
是用作它们之间的适配器)。幸运的是,
HttpContext
本身是可伪造的,足以让您替换IPrincipal
(用户)和IIdentity
。即使在控制台应用程序中,以下代码也会按预期运行:
HttpContext.Current
returns an instance ofSystem.Web.HttpContext
, which does not extendSystem.Web.HttpContextBase
.HttpContextBase
was added later to addressHttpContext
being difficult to mock. The two classes are basically unrelated (HttpContextWrapper
is used as an adapter between them).Fortunately,
HttpContext
itself is fakeable just enough for you do replace theIPrincipal
(User) andIIdentity
.The following code runs as expected, even in a console application:
下面的 Test Init 也将完成这项工作。
Below Test Init will also do the job.
我知道这是一个较旧的主题,但是模拟 MVC 应用程序进行单元测试是我们经常做的事情。
我只是想添加升级到 Visual Studio 2013 后使用 Moq 4 模拟 MVC 3 应用程序的经验。没有一个单元测试在调试模式下工作,并且在尝试查看变量时 HttpContext 显示“无法计算表达式” 。
结果 Visual Studio 2013 在评估某些对象时出现问题。为了让调试模拟的 Web 应用程序再次工作,我必须在 Tools=>Options=>Debugging=>General 设置中检查“使用托管兼容模式”。
我通常会这样做:
并像这样启动上下文
并直接调用控制器中的方法
I know this is an older subject, however Mocking a MVC application for unit tests is something we do on very regular basis.
I just wanted to add my experiences Mocking a MVC 3 application using Moq 4 after upgrading to Visual Studio 2013. None of the unit tests were working in debug mode and the HttpContext was showing "could not evaluate expression" when trying to peek at the variables.
Turns out visual studio 2013 has issues evaluating some objects. To get debugging mocked web applications working again, I had to check the "Use Managed Compatibility Mode" in Tools=>Options=>Debugging=>General settings.
I generally do something like this:
And initiating the context like this
And calling the Method in the controller straight forward
如果您的应用程序第三方内部重定向,那么最好通过以下方式模拟 HttpContext :
If your application third party redirect internally, so it is better to mock HttpContext in below way :