Asp.net core 在与Asp.Net Core TestServer的集成测试中设置虚拟IP地址
我有一个C#Asp.Net Core(1.x)项目,它实现了一个web REST API及其相关的集成测试项目,在任何测试之前,都有一个类似以下的设置:Asp.net core 在与Asp.Net Core TestServer的集成测试中设置虚拟IP地址,asp.net-core,integration-testing,asp.net-core-webapi,Asp.net Core,Integration Testing,Asp.net Core Webapi,我有一个C#Asp.Net Core(1.x)项目,它实现了一个web REST API及其相关的集成测试项目,在任何测试之前,都有一个类似以下的设置: /。。。 IWebHostBuilder webHostBuilder=GetWebHostBuildersMilarToRealOne() .UseStartup(); TestServer服务器=新的TestServer(webHostBuilder); server.BaseAddress=新Uri(“http://localhost:5
/。。。
IWebHostBuilder webHostBuilder=GetWebHostBuildersMilarToRealOne()
.UseStartup();
TestServer服务器=新的TestServer(webHostBuilder);
server.BaseAddress=新Uri(“http://localhost:5000");
HttpClient=server.CreateClient();
// ...
在测试期间,客户端
用于向web API(测试中的系统)发送HTTP请求并检索响应
在实际的测试系统中,有一些组件从每个请求中提取发送方IP地址,如下所示:
HttpContext HttpContext=ReceiveHttpContextDuringAuthentication();
//为简洁起见,省略了边缘情况
字符串remoteIpAddress=httpContext?.Connection?.remoteIpAddress?.ToString()
现在,在集成测试期间,这段代码找不到IP地址,因为RemoteIpAddress
始终为空
有没有办法从测试代码中将其设置为某个已知值?我一直在这里搜索,但没有找到类似的东西。TA您可以编写中间件来设置自定义IP地址,因为此属性是可写的:
公共类fakeremoteipAddress中间件
{
私有只读请求委托下一步;
private readonly IPAddress fakeIpAddress=IPAddress.Parse(“127.168.1.32”);
公共FakeRemoteIpAddressMiddleware(RequestDelegate下一步)
{
this.next=next;
}
公共异步任务调用(HttpContext HttpContext)
{
httpContext.Connection.RemoteIpAddress=fakeIpAddress;
等待这个。下一步(httpContext);
}
}
然后您可以像这样创建StartupStub
类:
公共类StartupStub:启动
{
公共StartupStub(IConfiguration配置):基本(配置)
{
}
公共覆盖无效配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
app.UseMiddleware();
配置(应用程序、环境);
}
}
并使用它创建一个TestServer
:
newtestserver(newWebHostBuilder().UseStartup());
根据此答案
还可以从ConfigureServices配置中间件,这允许您创建自定义WebApplicationFactory,而无需StartupStub类:
公共类CustomWebApplicationFactory:WebApplicationFactory
{
受保护的覆盖IWebHostBuilder CreateWebHostBuilder()
{
返回网络主机
.CreateDefaultBuilder(新字符串[0])
.ConfigureServices(服务=>
{
services.AddSingleton();
});
}
}
公共类CustomStartupFilter:IStartupFilter
{
公共操作配置(下一步操作)
{
返回应用=>
{
app.UseMiddleware();
下一步(应用程序);
};
}
}
使用WebHost.CreateDefaultBuilder可能会弄乱应用程序配置
除非绝对必要,否则不需要仅仅为了适应测试而更改产品代码
添加自己的中间件而不重写启动类方法的最简单方法是通过IStartupFilter添加中间件代码>如Elliott的回答所示
但是不要使用WebHost.CreateDefaultBuilder
,只需使用
base.CreateWebHostBuilder().ConfigureServices...
public class CustomWAF : WebApplicationFactory<Startup>
{
protected override IWebHostBuilder CreateWebHostBuilder()
{
return base.CreateWebHostBuilder().ConfigureServices(services =>
{
services.AddSingleton<IStartupFilter, CustomStartupFilter>();
});
}
}
base.CreateWebHostBuilder().ConfigureServices。。。
公共类CustomWAF:WebApplicationFactory
{
受保护的覆盖IWebHostBuilder CreateWebHostBuilder()
{
返回base.CreateWebHostBuilder().ConfigureServices(服务=>
{
services.AddSingleton();
});
}
}
ShowReceiveHttpContextDuringAuthentication()
这只是一个虚构的函数,用来表示正在发生的事情。在实际代码中,IP地址是在身份验证框架()提供的扩展点内提取的。该框架将当前请求HttpContext
作为一个输入传递给扩展点。看起来这可能是缺少的部分。例如,谢谢你,我会尝试一下,但是是的,它看起来很有前途。你也使用了dotnet core 2.x吗?看起来“Configure”在2.x中无法再被覆盖。@Ralf您是否在启动
类中将配置
标记为虚拟
?@PavelAgarkov您的解决方案是在中间件中对IP进行硬编码,这意味着所有集成测试都将使用相同的IP地址。是否还有一种方法可以声明每个测试用例单独使用的IP(例如,在创建HttpRequest时),以便可以考虑各种测试场景(具有各种IP地址)?@Dario,当然,您可以使用ConfigureTestServices注册一些服务,这些服务将注入FakeremoteiPadressMiddleware并用于获取当前ip地址。通过这种方式,您可以在使用客户端之前指定不同的ip地址。感谢您花时间回答这个问题,即使它比较旧。现在我离一个类似的项目还很远,让我们看看新项目会发生什么。非常感谢你的回答。如果不继承一个新的启动类(有其自身的缺点),直接通过WebApplicationFactory
配置其他中间件是不可能的,但是这种方法非常有效。对于使用.NET 5或Core 3.x的人来说,.ConfigureServices调用应该放在protected override IHost CreateHost中(IHostBuilder)
而不是CreateWebHostBuilder