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

如何为OAuth授权控制器单元测试配置GetOpenIddictServerRequest

如何在MS Tests中配置GetOpenIddictServerRequest进行控制器单元测试

我正在使用MS Tests编写基于OAuth授权的控制器单元测试,了解直接Mock HttpContext并非最佳实践,希望获得配置GetOpenIddictServerRequest的帮助。

相关代码片段

控制器端点代码

public async Task<IActionResult> Authorize()
{
    var request = HttpContext.GetOpenIddictServerRequest() ??
        throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");

    // 如果客户端指定了prompt=login,直接将用户代理重定向到登录页面
    if (request.HasPrompt(Prompts.Login))
    {
        // 为避免无限的登录->授权重定向,在重定向用户前从授权请求负载中移除prompt=login标志
        var prompt = string.Join(" ", request.GetPrompts().Remove(Prompts.Login));

        var parameters = Request.HasFormContentType ?
            Request.Form.Where(parameter => parameter.Key != Parameters.Prompt).ToList() :
            Request.Query.Where(parameter => parameter.Key != Parameters.Prompt).ToList();

        parameters.Add(KeyValuePair.Create(Parameters.Prompt, new StringValues(prompt)));

        return Challenge(
            authenticationSchemes: IdentityConstants.ApplicationScheme,
            properties: new AuthenticationProperties
            {
                RedirectUri = Request.PathBase + Request.Path + QueryString.Create(parameters)
            });
    }

    // 省略其他逻辑
}

GetOpenIddictServerRequest扩展方法

public static OpenIddictRequest? GetOpenIddictServerRequest(this HttpContext context)
{
    if (context == null)
    {
        throw new ArgumentNullException("context");
    }

    return context.Features.Get<OpenIddictServerAspNetCoreFeature>()?.Transaction?.Request;
}   

我尝试的HttpContext设置代码

_authorizationController.ControllerContext = new ControllerContext() { HttpContext = new DefaultHttpContext() {   } };

解决方案

不需要Mock整个HttpContext,直接模拟OpenIddict依赖的Feature和Transaction即可,步骤如下:

  • 创建并配置OpenIddictRequest实例,设置测试需要的属性(比如Prompt)
  • 实例化OpenIddictServerTransaction并关联上面的Request
  • 创建OpenIddictServerAspNetCoreFeature并关联Transaction
  • 将Feature添加到HttpContext的Features集合中
  • 把配置好的HttpContext赋值给控制器的ControllerContext

完整测试代码示例

// 1. 创建并配置OpenIddictRequest,模拟prompt=login的场景
var openIddictRequest = new OpenIddictRequest
{
    Prompt = Prompts.Login
};

// 2. 创建Transaction并关联Request
var transaction = new OpenIddictServerTransaction
{
    Request = openIddictRequest
};

// 3. 创建Feature并关联Transaction
var feature = new OpenIddictServerAspNetCoreFeature
{
    Transaction = transaction
};

// 4. 配置HttpContext并添加Feature
var httpContext = new DefaultHttpContext();
httpContext.Features.Set<OpenIddictServerAspNetCoreFeature>(feature);

// 5. 给控制器赋值配置好的HttpContext
_authorizationController.ControllerContext = new ControllerContext
{
    HttpContext = httpContext
};

// 执行测试方法
var result = await _authorizationController.Authorize();

// 断言结果,验证是否返回ChallengeResult
Assert.IsType<ChallengeResult>(result);

说明

这种方式贴合OpenIddict的内部调用逻辑,比Mock整个HttpContext更精准。如果需要测试其他场景(比如没有prompt=login的情况),只需要修改OpenIddictRequest的属性即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 04:35:46