模拟 HttpContext 时,SignOutAsync 失败

When mocking HttpContext, SignOutAsync fails

提问人:OutstandingBill 提问时间:11/9/2023 最后编辑:OutstandingBill 更新时间:11/10/2023 访问量:46

问:

我正在使用 Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions。SignOutAsync

在我的单元测试中,我在该扩展方法的某个地方得到了一个,它说ArgumentNullException

值不能为 null。(参数 'provider')

  Message: 
System.ArgumentNullException : Value cannot be null. (Parameter 'provider')

  Stack Trace: 
ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
AuthenticationHttpContextExtensions.SignOutAsync(HttpContext context, String scheme, AuthenticationProperties properties)
AuthenticationHttpContextExtensions.SignOutAsync(HttpContext context, String scheme)
AccountController.SignOut() line 123
AccountControllerTests.MyUnitTest() line 456
--- End of stack trace from previous location ---

我没有直接提供“provider”,因此我假设扩展方法是从 HttpContext 构建的。

我的测试中的 HttpContext 是使用 Moq 创建的:

var httpContext = new Mock<HttpContext>();

有没有办法哄骗我的模拟为“提供者”提供值?我是否需要切换到 DefaultHttpContext,并为 ?(很棘手,因为 DefaultHttpContext 不可模拟。ServiceScopeFactory

C# 单元测试 最小起订量 HTTPClient

评论

1赞 Dai 11/9/2023
请发布从哪里抛出的完整堆栈跟踪 - 有很多可能的控制路径,因此我们需要缩小范围......ArgumentNullExceptionSignOutAsync
0赞 OutstandingBill 11/10/2023
@Dai,谢谢,完成
0赞 Dai 11/10/2023
看起来您需要设置一个真实的(不是假的)和(来自)IMO。IHostIServiceProviderConfigureServices

答:

3赞 Etienne de Martel 11/9/2023 #1

如果你看一下源代码,最终会尝试调用一个私有方法,并且会尝试调用。SignOutAsyncGetAuthenticationServicecontext.RequestServices.GetService<IAuthenticationService>()

泛型是一个扩展方法,所以你的 null 实际上是 。 是抽象的,所以它将由 Moq 实现,默认情况下在松散的 mock 上,它只会返回 null。哎呀,你的崩溃了。GetServiceproviderRequestServicesRequestServicesHttpContext

所以,可以设置它:

IServiceProvider serviceProvider = /*...*/;

httpContext.SetupGet(x => x.RequestServices).Returns(serviceProvider);

但到那时,你可以只使用 a 并设置提供程序:DefaultHttpContext

var httpContext = new DefaultHttpContext
{
    RequestServices = serviceProvider
};

现在,您所需要的只是一个服务提供商。为此,请参阅此问题(您可以模拟一个问题,也可以从 ,创建一个问题)。ServiceCollection