如何unit testingHttpContext.SignInAsync()?

SignInAsync()源代码

我遇到了unit testing的一些问题。

  1. DefaultHttpContext.RequestServicesnull
  2. 我试图创建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