如何unit testingHttpContext.SignInAsync()?
SignInAsync()源代码
我遇到了unit testing的一些问题。
-
DefaultHttpContext.RequestServices
为null - 我试图创建
AuthenticationService
对象,但我不知道要传递什么参数
我该怎么办? 如何unit testingHttpContext.SignInAsync()
?
测试方法
public async Task Login(LoginViewModel vm, [FromQuery]string returnUrl) { if (ModelState.IsValid) { var user = await context.Users.FirstOrDefaultAsync(u => u.UserName == vm.UserName && u.Password == vm.Password); if (user != null) { var claims = new List { new Claim(ClaimTypes.Name, user.UserName) }; var identity = new ClaimsIdentity(claims, "HappyDog"); // here await HttpContext.SignInAsync(new ClaimsPrincipal(identity)); return Redirect(returnUrl ?? Url.Action("Index", "Goods")); } } return View(vm); }
到目前为止我尝试了什么。
[TestMethod] public async Task LoginTest() { using (var context = new HappyDogContext(_happyDogOptions)) { await context.Users.AddAsync(new User { Id = 1, UserName = "test", Password = "password", FacePicture = "FacePicture" }); await context.SaveChangesAsync(); var controller = new UserController(svc, null) { ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext { // How mock RequestServices? // RequestServices = new AuthenticationService()? } } }; var vm = new LoginViewModel { UserName = "test", Password = "password" }; var result = await controller.Login(vm, null) as RedirectResult; Assert.AreEqual("/Goods", result.Url); } }
HttpContext.SignInAsync
是一个使用RequestServices
的扩展方法,它是IServiceProvider
。 那是你必须嘲笑的。
context.RequestServices .GetRequiredService() .SignInAsync(context, scheme, principal, properties);
您可以通过创建从使用的接口派生的类或使用像Moq
这样的模拟框架来手动创建伪/模拟
//...code removed for brevity var authServiceMock = new Mock(); authServiceMock .Setup(_ => _.SignInAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(Task.FromResult((object)null)); var serviceProviderMock = new Mock(); serviceProviderMock .Setup(_ => _.GetService(typeof(IAuthenticationService))) .Returns(authServiceMock.Object); var controller = new UserController(svc, null) { ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext { // How mock RequestServices? RequestServices = serviceProviderMock.Object } } }; //...code removed for brevity
您可以像其他依赖项一样轻松地模拟HttpContext
。
您可以在快速入门时阅读有关如何使用Moq的信息
万一你们正在寻找NSubstitue的例子(Asp.net核心)。
IAuthenticationService authenticationService = Substitute.For(); authenticationService .SignInAsync(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()).Returns(Task.FromResult((object) null)); var serviceProvider = Substitute.For(); var authSchemaProvider = Substitute.For(); var systemClock = Substitute.For(); authSchemaProvider.GetDefaultAuthenticateSchemeAsync().Returns(Task.FromResult (new AuthenticationScheme("idp", "idp", typeof(IAuthenticationHandler)))); serviceProvider.GetService(typeof(IAuthenticationService)).Returns(authenticationService); serviceProvider.GetService(typeof(ISystemClock)).Returns(systemClock); serviceProvider.GetService(typeof(IAuthenticationSchemeProvider)).Returns(authSchemaProvider); context.RequestServices.Returns(serviceProvider); // Your act goes here // Your assert goes here