2

我是ASP.Net MVCIdentity的新手。在ASP.Net MVC注册码上运行单元测试时出错使用ASP.Net身份

我有以下单元测试方法。

[TestMethod] 
public void SignUp() 
{ 
    try 
    { 
     var dummyUser = new ApplicationUser() { UserName = "xyz", Email = "[email protected]" }; 

     ViewModels.RegisterViewModel rvm = new ViewModels.RegisterViewModel { Name = "abc", Email = "[email protected]", Password = "123456" }; 

     var store = new Mock<IUserStore<ApplicationUser>>(); 

     store.As<IUserPasswordStore<ApplicationUser>>() 
      .Setup(x => x.FindByIdAsync(It.IsAny<string>())) 
      .ReturnsAsync(new ApplicationUser() { Id = "id" }); 
     store.Setup(x => x.CreateAsync(dummyUser)).Returns(Task.FromResult(IdentityResult.Success)); 

     store.As<IUserRoleStore<ApplicationUser>>().Setup(x => x.AddToRoleAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>())).Returns(Task.FromResult(IdentityResult.Success)); 
     store.As<IUserRoleStore<ApplicationUser>>().Setup(x => x.IsInRoleAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>())).ReturnsAsync(true); 
     store.As<IRoleStore<IdentityRole>>().Setup(x => x.CreateAsync(new IdentityRole("I"))).Returns(Task.FromResult(IdentityResult.Success)); 

     //var roleStore = new Mock<IRoleStore<IdentityRole>>(); 
     //roleStore.As<IRoleStore<IdentityRole>>(); 
     //roleStore.Setup(x => x.CreateAsync(new IdentityRole("I"))).Returns(Task.FromResult(IdentityResult.Success)); 
     //var testRoleManager = new ApplicationRoleManager(roleStore.Object); 

     //to register usertokenprovider as it is needed to send confirmation email  
     var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("Sample"); 
     var testUserManager = new ApplicationUserManager(store.Object); 
     testUserManager.UserTokenProvider =new DataProtectorTokenProvider<ApplicationUser>(provider.Create("ASP.NET Identity")); 

     // mocking IAuthenticationManager 
     var mockAuthenticationManager = new Mock<IAuthenticationManager>(); 
     mockAuthenticationManager.Setup(am => am.SignOut()); 
     mockAuthenticationManager.Setup(am => am.SignIn()); 

     //mocking Context 
     var routes = new System.Web.Routing.RouteCollection(); 
     ProChartSiteMVC.RouteConfig.RegisterRoutes(routes); 

     var request = new Mock<HttpRequestBase>(MockBehavior.Strict); 
     request.SetupGet(x => x.ApplicationPath).Returns("/"); 
     request.SetupGet(x => x.Url).Returns(new Uri("http://localhost:1431/a", UriKind.Absolute)); 
     request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection()); 

     var response = new Mock<HttpResponseBase>(MockBehavior.Strict); 
     response.Setup(x => x.ApplyAppPathModifier("/post1")).Returns("http://localhost:1431/post1"); 

     var context = new Mock<HttpContextBase>(MockBehavior.Strict); 
     context.SetupGet(x => x.Request).Returns(request.Object); 
     context.SetupGet(x => x.Response).Returns(response.Object); 

     var testSignInManager = new ApplicationSignInManager(testUserManager,mockAuthenticationManager.Object); 

     BussinessLayer bussinessLayer = new BussinessLayer(db); 

     AccountController controller = new AccountController(testUserManager,testSignInManager, bussinessLayer); 
     var UrlHelperMock = new Mock<UrlHelper>(); 
     controller.Url = UrlHelperMock.Object; 

     controller.ControllerContext = new ControllerContext(context.Object, new System.Web.Routing.RouteData(), controller); 

     var result = controller.SignUp(rvm) as Task<ActionResult>; 
     var viewresult = result.Result; 
     Assert.IsNotNull(result); 
    } 
    catch (Exception ex) { string str = ex.ToString(); } 
} 

原始注册方法,当我运行调试模式,工作正常,但如果从单元测试执行提供了错误。

[HttpPost] 
public async Task<ActionResult> SignUp(RegisterViewModel rvm) 
{ 
    if (ModelState.IsValid) 
    {    
     var appUser = new ApplicationUser(); 
     appUser.UserName = bLayer.GenerateInvestarID(rvm.Email); 
     appUser.Email = rvm.Email; 
     appUser.Name = rvm.Name; 
     appUser.LockoutEnabled = true; 
     appUser.InstituteCode = "10"; 
     try 
     { 
      var result = await UserManager.CreateAsync(appUser, rvm.Password); 
      if (result.Succeeded) 
      { 
       IdentityResult addResult = await UserManager.AddToRoleAsync(appUser.Id, "I"); 
       await SignInManager.SignInAsync(appUser, isPersistent: false, rememberBrowser: false); 
       string code = await UserManager.GenerateEmailConfirmationTokenAsync(appUser.Id); 
       var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = appUser.Id, code = code }, protocol: Request.Url.Scheme); 
       await UserManager.SendEmailAsync(appUser.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>"); 
       return RedirectToAction("Thankyou"); 
      } 
      else 
      { 
       AddErrors(result); 
       return PartialView("_PartialSignUp", rvm); 
      } 
     } 
     catch(Exception ex) 
     { 
      ModelState.AddModelError("CredentialError", ex.Message); 
      return PartialView("_PartialSignUp", rvm); 
     } 
    } 
    else 
    { 
     ModelState.AddModelError("CredentialError", "Invalid Details"); 
     return PartialView("_PartialSignUp", rvm); 
    } 
} 

我获得以下错误而IdentityResult addResult =等待UserManager.AddToRoleAsync(appUser.Id, “I”)由上述代码通过单元测试执行。

System.NullReferenceException was caught 
    _HResult=-2147467261 
    _message=Object reference not set to an instance of an object. 
    HResult=-2147467261 
    IsTransient=false 
    Message=Object reference not set to an instance of an object. 
    Source=Microsoft.AspNet.Identity.Core 
    StackTrace: 
     at Microsoft.AspNet.Identity.UserManager`2.<AddToRoleAsync>d__83.MoveNext() 
    --- End of stack trace from previous location where exception was thrown --- 
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
     at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
     at SiteMVC.Controllers.AccountController.<SignUp>d__0.MoveNext() 

这是什么问题导致上述错误。

+0

对我来说,它看起来像你需要为'IUserStore.GetRolesAsync'方法'UserManager.AddToRoleAsync'方法建立结果调用'IUserStore.GetRolesAsync'并呼吁角色返回的集合'Contains'方法。由于在单元测试中没有为此方法设置结果,因此它将返回null作为引起此异常发生的默认值。 –

回答

3

对我来说,看起来你需要为IUserStore.GetRolesAsync方法设置结果。

UserManager.AddToRoleAsync方法调用IUserStore.GetRolesAsync并在返回的角色集上调用'Contains'方法。

由于在单元测试中没有设置此方法的结果,因此它会返回null作为导致发生此异常的默认值。

以下是我设置了IUserStore.GetRolesAsync返回空角色列表的结果的代码。

[TestMethod] 
public void SignUp() 
{ 
    try 
    { 
     var dummyUser = new ApplicationUser() { UserName = "xyz", Email = "[email protected]" }; 

     ViewModels.RegisterViewModel rvm = new ViewModels.RegisterViewModel { Name = "abc", Email = "[email protected]", Password = "123456" }; 

     var store = new Mock<IUserStore<ApplicationUser>>(); 

     var roles = new List<string>(); // Populate this list as per your need. 

     store.As<IUserPasswordStore<ApplicationUser>>() 
      .Setup(x => x.FindByIdAsync(It.IsAny<string>())) 
      .ReturnsAsync(new ApplicationUser() { Id = "id" }); 

     store.Setup(x => x.CreateAsync(dummyUser)).Returns(Task.FromResult(IdentityResult.Success)); 

     //Setting up the result for GetRoleAsync method to return roles collection. 
     store.As<IUserRoleStore<ApplicationUser>>().Setup(x => x.GetRolesAsync(It.IsAny<ApplicationUser>())).ReturnsAsync(roles); 

     //Rest of the unit test code 
    } 
    catch (Exception ex) { string str = ex.ToString(); } 
} 
+0

谢谢Chetan。它解决了我的问题。 – rikencpatel

+0

令人惊讶的是我找不到如何在其他地方设置它。谢谢! – Tim