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

.NET Core单元测试:ForwardedHeaders配置及中间件上下文验证

.NET Core扩展方法单元测试实现方案

一、验证AddProxyForwardedHeaders配置是否正确

这个扩展方法的核心是配置ForwardedHeadersOptions,无需启动TestServer,直接从服务容器中解析配置项断言即可,高效且直接。

测试思路

  1. 创建空的ServiceCollection实例
  2. 调用AddProxyForwardedHeaders扩展方法
  3. 构建服务提供者,获取配置好的ForwardedHeadersOptions
  4. 逐一验证各项配置是否符合预期

测试代码示例(xUnit)

using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.HttpOverrides;
using Xunit;

public class ProxyForwardedHeadersExtensionsTests
{
    [Fact]
    public void AddProxyForwardedHeaders_ConfiguresOptionsCorrectly()
    {
        // Arrange
        var services = new ServiceCollection();

        // Act
        services.AddProxyForwardedHeaders();
        var serviceProvider = services.BuildServiceProvider();
        var options = serviceProvider.GetRequiredService<IOptions<ForwardedHeadersOptions>>().Value;

        // Assert
        Assert.Null(options.ForwardLimit);
        Assert.False(options.RequireHeaderSymmetry);
        Assert.Empty(options.KnownNetworks);
        Assert.Empty(options.KnownProxies);
        Assert.Equal(
            ForwardedHeaders.XForwardedHost | ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
            options.ForwardedHeaders);
    }
}

二、验证UseProxyForwardedHeaders中间件的上下文修改逻辑

针对中间件的测试,提供两种可行方案:通过TestServer模拟请求,或直接构造HttpContext测试中间件逻辑。

方案1:使用TestServer模拟请求

通过自定义端点捕获请求上下文状态,验证中间件的修改效果。

测试代码示例

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Hosting;
using Xunit;
using System.Net.Http;
using System.Threading.Tasks;

public class ProxyForwardedHeadersMiddlewareTests
{
    [Theory]
    [InlineData("/my-service", "/my-service", "https")]
    [InlineData("", "/", "http")] // 空服务名时保持原Scheme和PathBase
    public async Task UseProxyForwardedHeaders_ModifiesContextCorrectly(string serviceName, string expectedPathBase, string expectedScheme)
    {
        // Arrange
        var hostBuilder = new HostBuilder()
            .ConfigureWebHost(webBuilder =>
            {
                webBuilder
                    .UseTestServer()
                    .ConfigureServices(services => services.AddRouting())
                    .Configure(app =>
                    {
                        app.UseProxyForwardedHeaders(serviceName);
                        // 自定义端点返回当前请求的Scheme和PathBase
                        app.UseEndpoints(endpoints =>
                        {
                            endpoints.MapGet("/", context =>
                            {
                                var result = $"Scheme:{context.Request.Scheme};PathBase:{context.Request.PathBase}";
                                return context.Response.WriteAsync(result);
                            });
                        });
                    });
            });

        var host = await hostBuilder.StartAsync();
        var client = host.GetTestClient();

        // Act
        var response = await client.GetAsync("/");
        response.EnsureSuccessStatusCode();
        var content = await response.Content.ReadAsStringAsync();

        // Assert
        Assert.Contains($"Scheme:{expectedScheme}", content);
        Assert.Contains($"PathBase:{expectedPathBase}", content);
    }
}

方案2:直接测试中间件委托

无需启动服务器,手动构造HttpContext和中间件委托,验证逻辑正确性。

测试代码示例

using Microsoft.AspNetCore.Http;
using Xunit;
using System.Threading.Tasks;

public class ProxyForwardedHeadersMiddlewareDirectTests
{
    [Fact]
    public async Task UseProxyForwardedHeaders_WithValidServiceName_ModifiesSchemeAndPathBase()
    {
        // Arrange
        var context = new DefaultHttpContext();
        context.Request.Scheme = "http";
        context.Request.PathBase = new PathString("");
        string serviceName = "/test-service";

        bool nextCalled = false;
        Task next()
        {
            nextCalled = true;
            return Task.CompletedTask;
        }

        // 提取中间件核心逻辑
        var testMiddleware = new Func<HttpContext, Func<Task>, Task>((ctx, nextFunc) =>
        {
            if (string.IsNullOrWhiteSpace(serviceName))
            {
                return nextFunc();
            }
            ctx.Request.Scheme = "https";
            ctx.Request.PathBase = new PathString(serviceName);
            return nextFunc();
        });

        // Act
        await testMiddleware(context, next);

        // Assert
        Assert.True(nextCalled);
        Assert.Equal("https", context.Request.Scheme);
        Assert.Equal(serviceName, context.Request.PathBase.Value);
    }

    [Fact]
    public async Task UseProxyForwardedHeaders_WithEmptyServiceName_DoesNotModifyContext()
    {
        // Arrange
        var context = new DefaultHttpContext();
        context.Request.Scheme = "http";
        context.Request.PathBase = new PathString("/original");
        string serviceName = "";

        bool nextCalled = false;
        Task next()
        {
            nextCalled = true;
            return Task.CompletedTask;
        }

        var testMiddleware = new Func<HttpContext, Func<Task>, Task>((ctx, nextFunc) =>
        {
            if (string.IsNullOrWhiteSpace(serviceName))
            {
                return nextFunc();
            }
            ctx.Request.Scheme = "https";
            ctx.Request.PathBase = new PathString(serviceName);
            return nextFunc();
        });

        // Act
        await testMiddleware(context, next);

        // Assert
        Assert.True(nextCalled);
        Assert.Equal("http", context.Request.Scheme);
        Assert.Equal("/original", context.Request.PathBase.Value);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:51:16