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

时间:2018-03-12 20:56:51

标签: asp.net-core integration-testing 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();

// ...

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

在实际测试系统中,有一些组件从每个请求中提取发件人IP地址,如:

HttpContext httpContext = ReceiveHttpContextDuringAuthentication();

// edge cases omitted for brevity
string remoteIpAddress = httpContext?.Connection?.RemoteIpAddress?.ToString()

现在在集成测试期间,这段代码无法找到IP地址,因为RemoteIpAddress始终为空。

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

3 个答案:

答案 0 :(得分: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);
    }
}

然后你可以像这样创建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);
    }
}

并使用它来创建TestServer

new TestServer(new WebHostBuilder().UseStartup<StartupStub>());

答案 1 :(得分:3)

根据此答案in ASP.NET Core, is there any way to set up middleware from 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);
        };
    }
}

答案 2 :(得分:1)

使用WebHost.CreateDefaultBuilder会弄乱您的应用程序配置。

除非绝对必要,否则无需为了适应测试而更改产品代码。

添加自己的中间件而不覆盖Startup类方法的最简单方法是按照Elliott的答案通过struct ContentView: View { var body: some View { NavigationView{ VStack{ HStack{ Text("dd") }.frame(width: 500, height: 300) .background(Color.blue) Spacer() } .navigationBarItems(leading: Text("Title"), trailing: Button(action: { //some action }) { Text("Button") }) } } } 添加中间件。

但不要使用IStartupFilter‍,而要使用

WebHost.CreateDefaultBuilder