c# - Moq 不会调用 IAuthenticationManager SignIn 方法

标签 c# asp.net-mvc unit-testing asp.net-identity moq

我正在尝试通过验证 AuthenticationManager SignIn 方法是否已被调用一次来为成功登录运行单元测试这是我遇到的错误:

Message: Test method Portfolio.UnitTest.WebUI.Controllers.LoginControllerTests.Login_Verified_Authenticates_System_User threw exception: Moq.MockException: Expected invocation on the mock once, but was 0 times: m => m.SignIn(AuthenticationProperties, [ClaimsIdentity])

Configured setups: m => m.SignIn(AuthenticationProperties, [ClaimsIdentity])

Performed invocations: IAuthenticationManager.SignIn(AuthenticationProperties, [ClaimsIdentity])

甚至错误信息似乎也自相矛盾。

我的 Controller 类/方法:

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);   
    }

登录 Controller 测试:

[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 中运行该方法在 Controller 中调用得很好,但 Moq 似乎忽略了它。

有什么想法吗?

最佳答案

Nkosi 在对您的问题的评论中说:

在表达式中

m => m.SignIn(authenticationProperty, identity)

两个参数authenticationPropertyidentity必须“等于”实际传入的两个参数(由被测系统)。 Equals也是如此比较时返回真?

您可以使用 It.IsAny<AuthenticationProperties>()It.Is((AuthenticationProperties x) => x.IsPersistent)或类似的,如果需要的话。与 ClaimsIdentity 类似.那么 Moq 将不再需要 Equals平等。

关于c# - Moq 不会调用 IAuthenticationManager SignIn 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49359361/

相关文章:

c# - 测试订阅 EventAggregator

c# - 解释这个 : CheckBox checkbox = (CheckBox)sender;

c# - 如何遍历复杂类型对象列表并传递给调用 SQL 存储过程的方法

asp.net - 是否可以访问另一个项目中的MVC View ?

asp.net-mvc - EntityFramework.dll 中发生类型 'System.Data.Entity.ModelConfiguration.ModelValidationException' 的异常

c# - Web服务的自动化测试框架

python unittest assertRaises在assertRaises失败时抛出异常

c# - 如何验证日期?

c# - 将 SqlDataReader 移至外部函数对性能有何影响?

c# - 在 signalr 中管理多个浏览器选项卡