使用Asp.Net Core TestServer在集成测试中设置虚拟IP地址

sup*_*jos 12 integration-testing asp.net-core asp.net-core-webapi

我有一个C#Asp.Net Core(1.x)项目,实现了一个Web REST API及其相关的集成测试项目,在任何测试之前有一个类似于以下的设置:

// ...

IWebHostBuilder webHostBuilder = GetWebHostBuilderSimilarToRealOne()
    .UseStartup<MyTestStartup>();

TestServer server = new TestServer(webHostBuilder);
server.BaseAddress = new Uri("http://localhost:5000");

HttpClient client = server.CreateClient();

// ...
Run Code Online (Sandbox Code Playgroud)

在测试期间,client它用于向Web API(被测系统)发送HTTP请求并检索响应.

在实际测试的系统中,有一些组件从每个请求中提取发送方IP地址,如下所示:

HttpContext httpContext = ReceiveHttpContextDuringAuthentication();

// edge cases omitted for brevity
string remoteIpAddress = httpContext?.Connection?.RemoteIpAddress?.ToString()
Run Code Online (Sandbox Code Playgroud)

现在在集成测试期间,这段代码无法找到IP地址,因为RemoteIpAddress它总是为空.

有没有办法将其设置为测试代码中的某个已知值?我在这里搜索了SO,但找不到类似的东西.TA

Pav*_*kov 13

您可以编写中间件来设置自定义IP地址,因为此属性是可写的:

public class FakeRemoteIpAddressMiddleware
{
    private readonly RequestDelegate next;
    private readonly IPAddress fakeIpAddress = IPAddress.Parse("127.168.1.32");

    public FakeRemoteIpAddressMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        httpContext.Connection.RemoteIpAddress = fakeIpAddress;

        await this.next(httpContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以创建这样的StartupStub类:

public class StartupStub : Startup
{
    public StartupStub(IConfiguration configuration) : base(configuration)
    {
    }

    public override void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseMiddleware<FakeRemoteIpAddressMiddleware>();
        base.Configure(app, env);
    }
}
Run Code Online (Sandbox Code Playgroud)

并用它来创建一个TestServer:

new TestServer(new WebHostBuilder().UseStartup<StartupStub>());
Run Code Online (Sandbox Code Playgroud)

  • @Ralf你在`Startup`课程中将`Configure`标记为`virtual`吗? (3认同)

Ell*_*ott 6

按照ASP.NET Core中的此答案,是否可以通过Program.cs设置中间件?

还可以从ConfigureServices配置中间件,该中间件使您无需StartupStub类即可创建自定义WebApplicationFactory:

public class CustomWebApplicationFactory : WebApplicationFactory<Startup>
{
    protected override IWebHostBuilder CreateWebHostBuilder()
    {
        return WebHost
            .CreateDefaultBuilder<Startup>(new string[0])
            .ConfigureServices(services =>
            {
                services.AddSingleton<IStartupFilter, CustomStartupFilter>();
            });
    }
}


public class CustomStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        return app =>
        {
            app.UseMiddleware<FakeRemoteIpAddressMiddleware>();
            next(app);
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢这个答案。如果不继承新的 Startup 类(它有其自身的缺点),就不可能直接通过 WebApplicationFactory 配置额外的中间件,但这种方法非常有效。 (2认同)