我正在使用 xunit、respawn 和 webapplicationfactory 为 mediatr 处理程序设置一些集成测试....
最终由正在测试的 mediatr 处理程序调用的类之一..依赖于 IHttpContextAccessor,如下所示
我觉得我已经设置了我想要正确注入的“替换”单例,如下所示:
但是当集成测试运行时.. httpContextAccessor 不为 null,但 HttpContext 始终为 null。
我已经尝试了大约 600 万件事:(非常悲伤。
如何让 IHttpContextAccessor 正确解析我在 ConfigureServices 中设置的内容?
当集成测试运行时.. httpContextAccessor 不为 null,但 HttpContext 始终为 null。如何让 IHttpContextAccessor 正确解析为我的内容 在ConfigureServices中设置?
不,我们不能,HttpContext 仅在请求范围内可用,因为在构造 Startup 之前调用了ConfigureServices,因此如果我们尝试注入,它将通过异常,即使我们在该场景中声明全局变量,它也将始终为 null 。应用程序启动仅发生一次,并且早在收到任何请求之前。
让我们尝试在 IConfiguration 中访问它,如下所示:
public Startup(IConfiguration configuration,IHttpContextAccessor httpContextAccessor)
{
Configuration = configuration;
HttpContextAccessor = httpContextAccessor;
}
public IConfiguration Configuration { get; }
public IHttpContextAccessor HttpContextAccessor { get; }
输出:
如您所见,它不允许我们这样做。
即使我们尝试将其注入配置本身,它最终也会出现以下异常:
因此,ConfigureServices 在任何 httprequest 到达应用程序之前运行一次。如果我们强行尝试在请求生命周期之外调用它,它总是会以 NullReferenceException 结束。您可以在官方文档中获得更多详细信息。
除此之外,我们还可以在配置中注入服务引用,如下所示:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
接受的答案也对我有用,但我的问题是我不小心添加了:
services.AddHttpContextAccessor();
在 ConfigureTestServices
方法内。所以最终的设置应该是这样的(因为接受的答案有图像而不是代码):
MockHttpContextAccessor.cs
public class MockHttpContextAccessor : IHttpContextAccessor
{
HttpContext? IHttpContextAccessor.HttpContext { get; set; } = new DefaultHttpContext
{
User = new GenericPrincipal(
new GenericIdentity("test-user"), new[] { "sample-role" })
};
}
WebApplicationFactory 类中的ConfigureWebHost 方法:
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureTestServices(services =>
{
services.AddSingleton<IHttpContextAccessor, MockHttpContextAccessor>();
});
}