Ошибка при выполнении модульного теста для регистрационного кода ASP.Net MVC, который использует ASP.Net Identity
Я новичок в ASP.Net MVC
а также Identity
,
У меня есть следующий метод модульного тестирования.
[TestMethod]
public void SignUp()
{
try
{
var dummyUser = new ApplicationUser() { UserName = "xyz", Email = "xyz@gmail.com" };
ViewModels.RegisterViewModel rvm = new ViewModels.RegisterViewModel { Name = "abc", Email = "abc@yahoo.com", 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(); }
}
Оригинальный метод SignUp, который отлично работает, когда я запускаю его в режиме отладки, но выдает ошибку, если выполняется из модульного теста.
[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 = await 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()
Что здесь происходит не так, что вызывает ошибку выше.
1 ответ
Мне кажется, вам нужно установить результат для метода IUserStore.GetRolesAsync.
Метод UserManager.AddToRoleAsync вызывает IUserStore.GetRolesAsync и вызывает метод "Содержит" возвращенной коллекции ролей.
Поскольку в модульном тесте нет результата для этого метода, он возвращает значение по умолчанию, которое вызвало возникновение этого исключения.
Ниже приведен код, для которого я настроил результат IUserStore.GetRolesAsync
вернуть пустой список ролей.
[TestMethod]
public void SignUp()
{
try
{
var dummyUser = new ApplicationUser() { UserName = "xyz", Email = "xyz@gmail.com" };
ViewModels.RegisterViewModel rvm = new ViewModels.RegisterViewModel { Name = "abc", Email = "abc@yahoo.com", 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(); }
}