You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试Razor Page的OnGetCurrencyAsync方法时如何模拟Request?

解决Razor页面单元测试中Request为null的问题

你遇到的问题根源是:Razor页面模型的Request、Url等属性依赖于HttpContext,直接实例化HomeModel时这些上下文属性不会自动初始化,导致调用Request.Headers时出现空引用错误。下面是具体的解决步骤和修改后的测试代码:

关键配置点

  • 模拟HttpContext并设置Request的Referer请求头
  • 配置UrlHelper,满足Url.IsLocalUrl和Url.Content的调用需求
  • 给HomeModel实例赋值HttpContext和Url属性
  • 模拟ICurrentUserService的相关方法(原方法中会调用,避免额外空引用)

修改后的完整测试代码

[Fact]
public async Task OnGetCurrencyAsync_ValidReferer_RedirectsToReferer()
{
    // 测试用的Referer地址
    var refererUrl = "https://localhost:44317/paris";
    var testCurrency = "EUR";

    // 模拟依赖服务
    var currentUserService = new Mock<ICurrentUserService>();
    var options = new Mock<IOptions<Core.Configuration.AppSettings>>();
    var navigationMenu = new Mock<INavigationMenu>();
    var productModelService = new Mock<IProductModelService>();
    var userSavedProductRepository = new Mock<IUserSavedProductRepository>();
    var userSavedProductService = new Mock<IUserSavedProductService>();

    // 模拟HttpContext和Request
    var mockHttpContext = new Mock<HttpContext>();
    var mockRequest = new Mock<HttpRequest>();
    
    // 设置Referer请求头
    var headers = new HeaderDictionary();
    headers["Referer"] = refererUrl;
    mockRequest.Setup(r => r.Headers).Returns(headers);
    
    // 设置Request的Scheme和Host,用于Url.IsLocalUrl判断
    mockRequest.Setup(r => r.Scheme).Returns("https");
    mockRequest.Setup(r => r.Host).Returns(HostString.FromUriComponent(refererUrl));
    
    mockHttpContext.Setup(c => c.Request).Returns(mockRequest.Object);

    // 创建ActionContext并初始化UrlHelper
    var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new PageActionDescriptor());
    var urlHelper = new UrlHelper(actionContext);

    // 实例化HomeModel并赋值上下文属性
    var homePage = new HomeModel(
        currentUserService.Object, 
        options.Object, 
        navigationMenu.Object, 
        productModelService.Object, 
        userSavedProductService.Object, 
        userSavedProductRepository.Object)
    {
        HttpContext = mockHttpContext.Object,
        Url = urlHelper
    };

    // 模拟CurrentUserService的方法,返回测试Session
    var testSession = new UserSession { Currency = "USD" };
    currentUserService.Setup(s => s.GetOrInitializeSessionAsync(It.IsAny<CancellationToken>()))
                      .ReturnsAsync(testSession);
    currentUserService.Setup(s => s.SetSession(It.IsAny<UserSession>(), It.IsAny<CancellationToken>()))
                      .Returns(Task.CompletedTask);

    // 执行测试方法
    var result = await homePage.OnGetCurrencyAsync(testCurrency, CancellationToken.None);

    // 断言验证
    var redirectResult = Assert.IsType<RedirectResult>(result);
    Assert.Equal(refererUrl, redirectResult.Url);
    
    // 验证Session的Currency是否被更新
    Assert.Equal(testCurrency, testSession.Currency);
    currentUserService.Verify(s => s.SetSession(testSession, It.IsAny<CancellationToken>()), Times.Once);
}

代码说明

  1. HttpContext模拟:通过Mock<HttpContext>和Mock<HttpRequest>设置请求头和请求基本信息,确保Request不为null,且能正确获取Referer值。
  2. UrlHelper配置:基于模拟的ActionContext创建UrlHelper,赋值给HomeModel的Url属性,保证Url.IsLocalUrl和Url.Content能正常工作。
  3. 服务模拟完善:补充了ICurrentUserService的方法模拟,避免测试过程中因未模拟服务方法导致的额外错误,同时可以验证Session是否被正确更新。

内容的提问来源于stack exchange,提问作者advapi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 08:31:01