我试图通过验证一次调用AuthenticationManager SignIn方法来运行成功登录的单元测试这是我得到的错误:
消息:测试方法Portfolio.UnitTest.WebUI.Controllers.LoginControllerTests.Login_Verified_Authenticates_System_User引发异常: Moq.MockException: 在模拟上预期调用一次,但是是0次:m => m.SignIn(AuthenticationProperties,[ClaimsIdentity])
已配置的设置: m => m.SignIn(AuthenticationProperties,[ClaimsIdentity])
执行调用: 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);
}
LoginControllerTests:
[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似乎忽略了它。
有什么想法吗?
答案 0 :(得分:3)
Nkosi在评论你的问题时说:
在表达式
中m => m.SignIn(authenticationProperty, identity)
两个参数authenticationProperty
和identity
必须是&#34;相等&#34;实际传入的两个参数(通过System-Under-Test)。那么Equals
在比较时会返回true吗?
如果需要,您可以使用It.IsAny<AuthenticationProperties>()
或It.Is((AuthenticationProperties x) => x.IsPersistent)
或类似内容。与ClaimsIdentity
类似。然后Moq将不再需要Equals
平等。