我已成功设置模拟以测试 asp.net 表单授权,但我看到角色成员身份和授权属性出现一些意外行为。具体来说,当如下所示调用 ChangePassword 方法时,我希望我会得到一个未经授权的访问重定向到登录屏幕,但是我可以一直通过 ChangePassword 方法并成功接收更改密码。谁能帮助指导我做错了什么?
我已经测试过,在 ChangePassword 方法中调用 IsUserInRole 方法确实可以按预期工作,并且我可以在这种情况下重定向到登录屏幕,但是在我的所有方法中测试这种情况似乎很麻烦。提前致谢。我也尝试过不将用户分配给角色(而不是使用模拟返回 false),但结果是一样的,更改密码成功。
[TestMethod]
public void TestProfile()
{
string testUserName = "userName", password = "password1", newPassword = "newPassword1";
var prov = new Mock<IMembershipProvider>();
prov.Setup(v => v.ValidateUser(testUserName, password)).Returns(true);
var user = new Mock<MembershipUser>();
var frmAuth = new Mock<IFormsAuthentication>();
user.Setup(v => v.ChangePassword(password, newPassword)).Returns(true);
prov.Setup(v => v.GetUser(testUserName, true)).Returns(user.Object);
AccountController ctrl = new AccountController(prov.Object, frmAuth.Object);
var ctrlCtx = new Mock<ControllerContext>();
ctrlCtx.SetupGet(x => x.HttpContext.User.Identity.Name).Returns(testUserName);
ctrlCtx.SetupGet(x => x.HttpContext.User.Identity.IsAuthenticated).Returns(true);
//with this line I would expect to see a redirect to unauhorized
ctrlCtx.Setup(x => x.HttpContext.User.IsInRole("RoleToTest")).Returns(false);
ctrl.ControllerContext = ctrlCtx.Object;
ctrl.Url = Moq.Mock.Of<IUrlHelper>(x => x.IsLocalUrl(It.IsAny<string>()) == true);
ChangePasswordModel changePass = new ChangePasswordModel() { NewPassword = newPassword, OldPassword = password, ConfirmPassword = password };
var result = ctrl.ChangePassword(changePass) as ViewResult;
string expectedViewName = "Logon";
Assert.AreEqual(result.ViewName, expectedViewName, true /* ignoreCase */,
string.Format("The expected view '{0}' was not returned. Did change password succeed?", expectedViewName));
}
[Authorize(Roles="RoleToTest")]
[HttpPost]
public ActionResult ChangePassword(ChangePasswordModel model)
{
if (ModelState.IsValid)
{
// ChangePassword will throw an exception rather
// than return false in certain failure scenarios.
bool changePasswordSucceeded;
try
{
MembershipUser currentUser = membershipProvider.GetUser(User.Identity.Name, true /* userIsOnline */);
changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
}
catch (Exception e)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(e);
changePasswordSucceeded = false;
}
if (changePasswordSucceeded)
{
return View("ChangePasswordSuccess");
}
else
{
ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
}
}
// If we got this far, something failed, redisplay form
return View("ChangePassword", model);
}