ASP.NET Core测试Action方法时如何Mock Session
测试AzureReportsController的ResourcesCustomReports方法:Session Mock方案
问题背景
作为Mock和测试领域新手,测试AzureReportsController的ResourcesCustomReports Action时遇到Session相关报错。该Action会生成Guid作为键,将文件字节数组存入Session,我已初始化控制器并设置DefaultHttpContext,但调用Session方法时出错,需要Mock Session以通过返回结果非空的断言。
原测试代码
var azureReportControllerUnderTest = new AzureReportsController(mockIlogger.Object, mockPrismRepository.Object, mockReportRepository.Object); azureReportControllerUnderTest.ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext(), }; azureReportControllerUnderTest.ControllerContext.HttpContext.Request.Headers.Add(HeaderNames.Cookie, selectedTenantCookie); azureReportControllerUnderTest.HttpContext.Session.Set(handle, memoryStream.ToArray()); azureReportControllerUnderTest.HttpContext.Session.Get(handle);
目标Action代码
[HttpGet] public IActionResult ResourcesCustomReports(DateTime? startingDate, DateTime? endingDate) { var selectedTenant = this.GetCurrentTenant(); var fileName = $"resources_report_tenant_id_{selectedTenant}.xlsx"; var workbook = this.reportsRepository.GetCustomDateResources(selectedTenant, startingDate, endingDate); string handle = Guid.NewGuid().ToString(); using (MemoryStream memoryStream = new MemoryStream()) { workbook?.SaveAs(memoryStream); memoryStream.Position = 0; this.HttpContext.Session.Set(handle, memoryStream.ToArray()); } return this.Json(new { FileGuid = handle, FileName = fileName }); }
断言代码
var result=azureReportControllerUnderTest.ResourcesCustomReports(to, from); Assert.IsNotNull(result);
解决方案
核心问题
DefaultHttpContext的默认Session未初始化,直接调用Set/Get会抛出异常,必须模拟一个可用的ISession实例。
实现步骤
- 用Moq模拟
ISession:模拟Session的Set和Get方法,无需真实存储逻辑,只需保证方法正常执行。 - 挂载Mock的Session到HttpContext:替换
DefaultHttpContext的Session属性为Mock实例。 - 确保
GetCurrentTenant返回有效值:如果该方法依赖请求信息,提前配置好对应请求头或状态,避免空引用影响后续逻辑。
修改后的完整测试代码
// 初始化Mock依赖 var mockIlogger = new Mock<ILogger<AzureReportsController>>(); var mockPrismRepository = new Mock<IPrismRepository>(); var mockReportRepository = new Mock<IReportRepository>(); // 模拟GetCurrentTenant返回的租户ID var selectedTenantId = "test-tenant-id"; var selectedTenantCookie = $"TenantId={selectedTenantId}"; // 模拟ISession var mockSession = new Mock<ISession>(); // 模拟Set方法,无需实际存储 mockSession.Setup(s => s.Set(It.IsAny<string>(), It.IsAny<byte[]>())) .Verifiable(); // 模拟Get方法,按需返回字节数组 mockSession.Setup(s => s.Get(It.IsAny<string>())) .Returns((string key) => null); // 初始化控制器并配置HttpContext var azureReportControllerUnderTest = new AzureReportsController(mockIlogger.Object, mockPrismRepository.Object, mockReportRepository.Object); var httpContext = new DefaultHttpContext(); httpContext.Request.Headers.Add(HeaderNames.Cookie, selectedTenantCookie); // 挂载Mock的Session httpContext.Session = mockSession.Object; azureReportControllerUnderTest.ControllerContext = new ControllerContext { HttpContext = httpContext }; // 调用Action并断言 var to = DateTime.Now; var from = DateTime.Now.AddDays(-7); var result = azureReportControllerUnderTest.ResourcesCustomReports(to, from); Assert.IsNotNull(result); // 可选:验证Session的Set方法是否被调用 mockSession.Verify(s => s.Set(It.IsAny<string>(), It.IsAny<byte[]>()), Times.Once);
内容的提问来源于stack exchange,提问作者Tim Whatley
相关产品推荐
相关产品推荐

