如何在AspNetCore.Authentication.Abstractions上模拟AuthenticateAsync

rya*_*cot 5 c# unit-testing mocking nsubstitute asp.net-core

我在控制器上有一个动作

var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
Run Code Online (Sandbox Code Playgroud)

我试图在这样的单元测试中模拟这个结果

httpContextMock.AuthenticateAsync(Arg.Any<string>()).Returns(AuthenticateResult.Success(...
Run Code Online (Sandbox Code Playgroud)

然而,这会抛出一个invalidoperationexception"类型'没有服务'Microsoft.AspNetCore.Authentication.IAuthenticationService'已注册"

模拟这种方法的正确方法是什么?

Nko*_*osi 6

那个扩展方法

/// <summary>
/// Extension method for authenticate.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/> context.</param>
/// <param name="scheme">The name of the authentication scheme.</param>
/// <returns>The <see cref="AuthenticateResult"/>.</returns>
public static Task<AuthenticateResult> AuthenticateAsync(this HttpContext context, string scheme) =>
    context.RequestServices.GetRequiredService<IAuthenticationService>().AuthenticateAsync(context, scheme);
Run Code Online (Sandbox Code Playgroud)

穿过IServiceProvider RequestServices酒店.

/// <summary>
/// Gets or sets the <see cref="IServiceProvider"/> that provides access to the request's service container.
/// </summary>
public abstract IServiceProvider RequestServices { get; set; }
Run Code Online (Sandbox Code Playgroud)

模拟服务提供商返回一个模拟IAuthenticationService,你应该能够通过测试伪造你的方式.

authServiceMock.AuthenticateAsync(Arg.Any<HttpContext>(), Arg.Any<string>())
    .Returns(Task.FromResult(AuthenticateResult.Success()));
providerMock.GetService(typeof(IAuthenticationService))
    .Returns(authServiceMock);
httpContextMock.RequestServices.Returns(providerMock);

//...
Run Code Online (Sandbox Code Playgroud)