我正在尝试通过验证身份验证管理器登录方法是否已调用一次来运行单元测试以成功登录 这是我收到的错误:
消息:引发异常Portfolio.UnitTest.WebUI.Controllers.LoginControllerTests.Login_Verified_Authenticates_System_User测试方法: 最小起订量模拟异常: 模拟的预期调用一次,但为 0 次:m => m.SignIn(AuthenticationProperties, [ClaimIdentity](
配置的设置: m => m.SignIn(AuthenticationProperties, [ClaimIdentity](
执行的调用: IAuthenticationManager.SignIn(AuthenticationProperties, [ClaimsIdentity](
甚至错误消息似乎也自相矛盾。
我的控制器类/方法:
public class LoginController : ProjectBaseController
{
private IAuthenticationManager _authenticationManager;
public IAuthenticationManager AuthenticationManager
{
get
{
return _authenticationManager ?? HttpContext.GetOwinContext().Authentication;
}
set
{
_authenticationManager = value;
}
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Index(LoginViewModel accountUser)
{
if (!ModelState.IsValid)
return View(accountUser);
var systemUser = _authenticationService.Verify(accountUser.Email, accountUser.Password);
if (systemUser == null)
{
ModelState.AddModelError("", "Invalid email address or password");
return View(accountUser);
}
var identity = new ClaimsIdentity
(
new[]
{
new Claim(ClaimTypes.Name, systemUser.FullName),
new Claim(ClaimTypes.Email, systemUser.Email)
},
DefaultAuthenticationTypes.ApplicationCookie,
ClaimTypes.Name,
ClaimTypes.Role
);
// Set roles for authorization attributes used throughout dashboard
foreach(var role in systemUser.Roles)
{
identity.AddClaim(new Claim(ClaimTypes.Role, role.Name));
}
AuthenticationManager.SignIn
(
new AuthenticationProperties
{
IsPersistent = true
},
identity
);
return Redirect(accountUser.ReturnUrl);
}
登录控制器测试:
[TestClass]
public class LoginControllerTests
{
private readonly Mock<IAuthenticationManager> _mockAuthenticationManager;
private readonly Mock<IAuthenticationService> _mockAuthenticationService;
public LoginControllerTests()
{
_mockAuthenticationManager = new Mock<IAuthenticationManager>();
_mockAuthenticationService = new Mock<IAuthenticationService>();
}
private LoginController GetLoginControllerInstance()
{
var controller = new LoginController(_mockAuthenticationService.Object);
controller.AuthenticationManager = _mockAuthenticationManager.Object;
return controller;
}
[TestMethod]
public void Login_Verified_Authenticates_System_User()
{
// Arrange
var viewModel = new LoginViewModel("/")
{
Email = "email@test.co.uk",
Password = "password-test"
};
var systemUser = new SystemUser()
{
Id = new Random().Next(),
FirstName = "Joe",
LastName = "Bloggs",
Email = viewModel.Email,
Password = viewModel.Password,
Roles = new List<Role>()
};
var identity = new ClaimsIdentity
(
new[]
{
new Claim(ClaimTypes.Name, systemUser.FullName),
new Claim(ClaimTypes.Email, systemUser.Email)
},
DefaultAuthenticationTypes.ApplicationCookie,
ClaimTypes.Name,
ClaimTypes.Role
);
var authenticationProperty = new AuthenticationProperties
{
IsPersistent = true
};
var controller = this.GetLoginControllerInstance();
_mockAuthenticationService.Setup(m => m.Verify(viewModel.Email, viewModel.Password))
.Returns(systemUser);
_mockAuthenticationManager.Setup(m => m.SignIn(authenticationProperty, identity));
// Act
var result = controller.Index(viewModel);
// Assert
Assert.IsNotNull(result);
Assert.IsTrue(controller.ModelState.IsValid);
_mockAuthenticationService.Verify(m => m.Verify(viewModel.Email, viewModel.Password), Times.Once);
_mockAuthenticationManager.Verify(m => m.SignIn(authenticationProperty, identity), Times.Once);
}
}
}
在 deubg 中运行该方法可以在控制器中调用,但 Moq 似乎忽略了它。
有什么想法吗?
Nkosi在对你的问题的评论中说:
在表达式中
m => m.SignIn(authenticationProperty, identity)
authenticationProperty
和identity
两个参数必须与实际传入的两个参数(由测试系统传递("相等"。那么,当你比较时,Equals
会返回真吗?
如果需要,您可以使用It.IsAny<AuthenticationProperties>()
或It.Is((AuthenticationProperties x) => x.IsPersistent)
或类似功能。类似于ClaimsIdentity
.那么最小起订量将不再需要Equals
平等。