集成测试中如何通过HttpClient传递Session Token?
问题
我的应用包含自定义中间件,用于从Session中获取字符串:
public Task Invoke(HttpContext httpContext) { //... string token = httpContext.Session.GetString("token"); //... }
现有如下集成测试代码:
public class UsersControllerTest { private readonly HttpClient _httpClient; private readonly TestServer _testServer; public UsersControllerTest() { var projectDir = @"c:\TestSessionApp"; _testServer = new TestServer(WebHost.CreateDefaultBuilder() .UseEnvironment("Development") .UseContentRoot(projectDir) .UseConfiguration(new ConfigurationBuilder() .SetBasePath(projectDir) .AddJsonFile("appsettings.Development.json") .Build() ) .UseStartup<Startup>()); _httpClient = _testServer.CreateClient(); } [Theory] [InlineData("GET")] public async Task TestGet(string methodType) { var requestMsg = new HttpRequestMessage(new HttpMethod(methodType), "/api/users"); //... ? var responseMsg = await _httpClient.SendAsync(requestMsg); } }
请问如何通过HttpClient传递Session字符串?是否需要模拟HttpContext?但这是集成测试,我希望尽可能少使用模拟。
解决方案
你好呀,其实在集成测试里传递Session完全不需要模拟HttpContext,咱们直接利用TestServer的原生能力就能搞定,完全贴合真实的运行逻辑,完美符合你“少用模拟”的需求~
核心思路是:Session是通过Cookie与请求关联的,我们可以直接在测试中创建真实的服务器端HttpContext,设置好Session值后,把对应的Session Cookie附加到HttpClient的请求里,这样中间件就能正常读取到Session中的token了。
具体修改你的测试方法即可:
[Theory] [InlineData("GET")] public async Task TestGet(string methodType) { // 1. 创建服务器端的HttpContext,操作Session var httpContext = _testServer.Server.CreateContext(); await httpContext.Session.LoadAsync(); // 设置你需要的测试token值 httpContext.Session.SetString("token", "your-test-token-value"); await httpContext.Session.CommitAsync(); // 2. 获取Session对应的Cookie var sessionCookie = httpContext.Response.Headers["Set-Cookie"].FirstOrDefault(); // 3. 构造请求并添加Session Cookie var requestMsg = new HttpRequestMessage(new HttpMethod(methodType), "/api/users"); if (!string.IsNullOrEmpty(sessionCookie)) { requestMsg.Headers.Add("Cookie", sessionCookie); } var responseMsg = await _httpClient.SendAsync(requestMsg); // 后续的断言逻辑... }
补充说明
- 这种方式完全复用了你的应用中配置的Session机制(包括Cookie名称、过期时间等),没有任何模拟,完全是集成测试的正确姿势。
- 如果你的Startup中自定义了Session的Cookie名称(比如
services.AddSession(options => options.Cookie.Name = "MyCustomSession")),那你需要从httpContext.Response.Cookies中找到对应名称的Cookie,再构造Cookie头。 Session.LoadAsync()和CommitAsync()是必须的,因为Session默认是惰性加载的,必须显式调用才能读写Session数据。
内容的提问来源于stack exchange,提问作者Adam Shakhabov
相关产品推荐
相关产品推荐

