C# 模拟ASP.NET标识的单元测试登录失败

C# 模拟ASP.NET标识的单元测试登录失败,c#,asp.net,asp.net-mvc,unit-testing,asp.net-identity,C#,Asp.net,Asp.net Mvc,Unit Testing,Asp.net Identity,我正在使用Moq和Microsoft的测试工具为使用ASP.NET标识的ASP.NET MVC 5应用程序编写一个单元测试。测试需要在登录后操作中模拟登录失败,以便从myAccountController的SignInManager.PasswordSignInAsync方法生成SignInStatus.failure: [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult

我正在使用Moq和Microsoft的测试工具为使用ASP.NET标识的ASP.NET MVC 5应用程序编写一个单元测试。测试需要在登录后操作中模拟登录失败,以便从my
AccountController的
SignInManager.PasswordSignInAsync
方法生成
SignInStatus.failure

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login([Bind(Include = "Email,Password,RememberMe")] 
    LoginViewModel model, string returnUrl)
{
    var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, 
        model.RememberMe, shouldLockout: true);
    switch (result)
    {
        case SignInStatus.Success:
            return Redirect(returnUrl);
        case SignInStatus.LockedOut:
            return View("Lockout");
        case SignInStatus.RequiresVerification:
        case SignInStatus.Failure:
        default:
            ModelState.AddModelError("", "Invalid login attempt.");
            return View(model);
    }   
}
这是我的测试方法:

[TestMethod]
public async Task NoViewReturnedForFailedLogin()
{
    // Arrange
    var claimsIdentity = new ClaimsIdentity();
    claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, "fake@fake.org"));
    var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
    SetContexts(claimsPrincipal);
    var vm = new LoginViewModel
    {
        Email = "faker@gmail.com",
        Password = "Faker9999!",
        RememberMe = false
    };

    _controllerContextMock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(vm.Email);
    _controllerContextMock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(false);

    // Act
    var result = await _controller.Login(vm, "http://www.google.com") as RedirectToRouteResult;

    // Assert
    // ? What do I assert?
}
如您所见,我有mock
userStore
userManager
authenticationManager
signInManager
。如果我单步执行
Login
操作,
result
始终返回
SignInStatus.Success


有没有办法让它失败?测试应该断言什么?

您需要为SignInManager.PasswordSignInAsync设置模拟以返回其他内容SeSignInManager.setup(p=>PasswordSignInAsync().ReturnsAsync(SignInStatus.Failure);您模拟的依赖项太多,而测试中的方法仅依赖于
SignInManager
。请设置该依赖项,使其按照测试和您的完成所需的方式运行。至于要断言的内容,请查看预期的代码路径,并断言结果符合预期。从创建的模拟中,似乎可以看到您的帐户控制器与实现问题紧密耦合,这也解释了为什么必须模拟如此多的依赖关系。类应该依赖于抽象而不是具体的实现。设置的数量表明您在错误的级别或错误的事情上进行测试。请后退一步,思考您实际要测试的内容以及原因。如果您尝试ng测试
登录管理器
-这是标识库的一部分,已经为您进行了测试。
[TestMethod]
public async Task NoViewReturnedForFailedLogin()
{
    // Arrange
    var claimsIdentity = new ClaimsIdentity();
    claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, "fake@fake.org"));
    var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
    SetContexts(claimsPrincipal);
    var vm = new LoginViewModel
    {
        Email = "faker@gmail.com",
        Password = "Faker9999!",
        RememberMe = false
    };

    _controllerContextMock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(vm.Email);
    _controllerContextMock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(false);

    // Act
    var result = await _controller.Login(vm, "http://www.google.com") as RedirectToRouteResult;

    // Assert
    // ? What do I assert?
}