我有一个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
答案 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