最近团队有小伙伴问在单元测试中如何Mock HttpContext. 这是一个好问题,整理了一个实现方案分享给大家。

在C#中,尤其是在单元测试场景下,模拟(Mocking)HttpContext 是一种常见的做法。这允许我们在没有实际HTTP请求的情况下测试与HTTP上下文相关的代码。

为了模拟HttpContext,我们通常会使用像Moq这样的库,它是.NET中一个流行的模拟框架。
以下是一个简单的示例,展示了如何使用Moq来模拟一个HttpContext:
首先,你需要安装Moq库。如果你使用的是.NET Core或.NET 5/6/7/8等较新版本,你可以通过NuGet包管理器来安装它:

dotnet add package Moq

或者,在Visual Studio中,你可以通过NuGet包管理器UI来搜索并安装Moq。

安装完成后,编写以下代码来创建一个模拟的HttpContext.

usingSystem.Security.Claims;usingSystem.Web;usingMoq;//创建一个模拟的HttpContext
var mockContext = new Mock<HttpContextBase>();//模拟HttpRequest
var mockRequest = new Mock<HttpRequestBase>();
mockRequest.Setup(r
=> r.ApplicationPath).Returns("/");
mockRequest.Setup(r
=> r.ServerVariables).Returns(newSystem.Collections.Specialized.NameValueCollection());
mockContext.Setup(c
=>c.Request).Returns(mockRequest.Object);//模拟HttpResponse var mockResponse = new Mock<HttpResponseBase>();
mockResponse.Setup(r
=> r.Cache).Returns(newHttpCachePolicyBase());
mockContext.Setup(c
=>c.Response).Returns(mockResponse.Object);//模拟HttpSessionState var mockSession = new Mock<HttpSessionStateBase>();
mockSession.Setup(s
=> s["MySessionItem"]).Returns("SessionValue");
mockContext.Setup(c
=>c.Session).Returns(mockSession.Object);//模拟HttpServerUtility var mockServer = new Mock<HttpServerUtilityBase>();
mockContext.Setup(c
=>c.Server).Returns(mockServer.Object);//模拟HttpUser var mockUser = new Mock<IPrincipal>();var mockIdentity = new Mock<IIdentity>();
mockIdentity.Setup(i
=> i.Name).Returns("User");
mockIdentity.Setup(i
=> i.IsAuthenticated).Returns(true);
mockUser.Setup(u
=>u.Identity).Returns(mockIdentity.Object);
mockContext.Setup(c
=>c.User).Returns(mockUser.Object);//现在你可以使用 mockContext.Object 来作为你的HttpContextBase对象了 var httpContext =mockContext.Object;//使用示例: var userName = httpContext.User.Identity.Name; //返回 "User" var isAuthenticated = httpContext.User.Identity.IsAuthenticated; //返回 true var mySessionItem = httpContext.Session["MySessionItem"]; //返回 "SessionValue"

更进一步,我们可以把这个HttpContext的mock封装成一个服务,团队其他的小伙伴也可以一起使用。

so,为了使其更加模块化和可重用,我们可以将这些模拟的创建过程封装到一个方法中,或者创建一个专门的服务类来提供
HttpContextBase
的模拟实例。

usingSystem.Collections.Specialized;usingSystem.Security.Principal;usingSystem.Web;usingMoq;public static classMockHttpContextService
{
public staticHttpContextBase CreateMockHttpContext(string userName = "User",bool isAuthenticated = true,string sessionKey = "MySessionItem",object sessionValue = null,string applicationPath = "/",
NameValueCollection serverVariables
= null)
{
var mockContext = new Mock<HttpContextBase>();//模拟HttpRequest var mockRequest = new Mock<HttpRequestBase>();
mockRequest.Setup(r
=>r.ApplicationPath).Returns(applicationPath);
mockRequest.Setup(r
=> r.ServerVariables).Returns(serverVariables ?? newNameValueCollection());
mockContext.Setup(c
=>c.Request).Returns(mockRequest.Object);//模拟HttpResponse var mockResponse = new Mock<HttpResponseBase>();
mockResponse.Setup(r
=> r.Cache).Returns(newHttpCachePolicyBase());
mockContext.Setup(c
=>c.Response).Returns(mockResponse.Object);//模拟HttpSessionState var mockSession = new Mock<HttpSessionStateBase>();if (sessionKey != null)
{
mockSession.Setup(s
=>s[sessionKey]).Returns(sessionValue);
}
mockContext.Setup(c
=>c.Session).Returns(mockSession.Object);//模拟HttpServerUtility var mockServer = new Mock<HttpServerUtilityBase>();
mockContext.Setup(c
=>c.Server).Returns(mockServer.Object);//模拟HttpUser var mockUser = new Mock<IPrincipal>();var mockIdentity = new Mock<IIdentity>();
mockIdentity.Setup(i
=>i.Name).Returns(userName);
mockIdentity.Setup(i
=>i.IsAuthenticated).Returns(isAuthenticated);
mockUser.Setup(u
=>u.Identity).Returns(mockIdentity.Object);
mockContext.Setup(c
=>c.User).Returns(mockUser.Object);returnmockContext.Object;
}
}

创建模拟
HttpContext
对象时传入自定义参数:

var httpContext =MockHttpContextService.CreateMockHttpContext(
userName:
"CustomUser",
isAuthenticated:
false,
sessionKey:
"CustomSessionItem",
sessionValue:
"CustomSessionValue",
applicationPath:
"/MyApp",
serverVariables:
new NameValueCollection { { "SERVER_NAME", "localhost"} }
);
//使用示例: var userName = httpContext.User.Identity.Name; //返回 "CustomUser" var isAuthenticated = httpContext.User.Identity.IsAuthenticated; //返回 false var mySessionItem = httpContext.Session["CustomSessionItem"]; //返回 "CustomSessionValue" var appPath = httpContext.Request.ApplicationPath; //返回 "/MyApp" var serverName = httpContext.Request.ServerVariables["SERVER_NAME"]; //返回 "localhost"

以上是单元测试中如何Mock HttpContext的分享,希望能帮助到大家。

周国庆

2024/1/24

标签: none

添加新评论