模拟ASP.NET身份的单元测试失败登录

时间:2018-01-09 13:08:54

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

我正在使用Moq和Microsoft的测试工具为使用ASP.NET身份的ASP.NET MVC 5应用编写单元测试。测试需要在Login POST操作中模拟登录失败,以便从SignInStatus.Failure的{​​{1}}方法生成SignInManager.PasswordSignInAsync

AccountController

以下是[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); } } 上的帮助成员/方法:

[TestClass]

这是我的测试方法:

private Mock<HttpContextBase> _httpContextMock;
private Mock<HttpRequestBase> _httpRequestMock;
private Mock<HttpResponseBase> _httpResponseMock;
private MyApp.Controllers.AccountController _controller;
private Mock<ControllerContext> _controllerContextMock;

[TestInitialize]
public void SetupTests()
{
    // Set up Moq
    _httpContextMock = new Mock<HttpContextBase>();
    _httpRequestMock = new Mock<HttpRequestBase>();
    _httpResponseMock = new Mock<HttpResponseBase>();
    _controller = new AccountController();
    _controllerContextMock = new Mock<ControllerContext>();
}

private void SetContexts(IPrincipal user)
{
    _httpContextMock.Setup(x => x.Items).Returns(new Dictionary<string, object>());
    var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(),
        new HttpStaticObjectsCollection(), 10, true,
        HttpCookieMode.AutoDetect,
        SessionStateMode.InProc, false);
    //this adds aspnet session
    _httpContextMock.Object.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
            BindingFlags.NonPublic | BindingFlags.Instance,
            null, CallingConventions.Standard,
            new[] { typeof(HttpSessionStateContainer) },
            null)
        .Invoke(new object[] { sessionContainer });
    _httpContextMock.Setup(x => x.User).Returns(user);

    // https://stackoverflow.com/questions/674458/asp-net-mvc-unit-testing-controllers-that-use-urlhelper
    _httpRequestMock.SetupGet(x => x.ApplicationPath).Returns("/");
    _httpRequestMock.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
    _httpRequestMock.SetupGet(x => x.ServerVariables).Returns(new NameValueCollection());

    _httpResponseMock.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(x => x);
    var routes = new RouteCollection();
    RouteConfig.RegisterRoutes(routes);
    var helper = new UrlHelper(new RequestContext(_httpContextMock.Object, new RouteData()), routes);

    _httpContextMock.SetupGet(x => x.Request).Returns(_httpRequestMock.Object);
    _httpContextMock.SetupGet(x => x.Response).Returns(_httpResponseMock.Object);

    // https://stackoverflow.com/questions/4066184/httpresponsebase-headers-are-empty-when-running-test
    _httpResponseMock.Setup(r => r.OutputStream).Returns(new MemoryStream());
    _httpResponseMock.Setup(r => r.Headers).Returns(new NameValueCollection());

    var userStore = new Mock<IUserStore<ApplicationUser>>();
    var userManager = new Mock<ApplicationUserManager>(userStore.Object);
    var authenticationManager = new Mock<IAuthenticationManager>();
    var signInManager = new Mock<ApplicationSignInManager>(userManager.Object, authenticationManager.Object);

    var data = new Dictionary<string, object>()
    {
        {"a", "b"} // fake whatever  you need here.
    };

    // https://stackoverflow.com/a/28574389/177416
    _controller = new AccountController(
        userManager.Object, signInManager.Object)
    {
        ControllerContext = new ControllerContext()
        {
            HttpContext = _httpContextMock.Object
        }
    }; 

    _controller.ControllerContext.HttpContext.Items["owin.Environment"] = data;
    _controller.Url = helper;
}

如您所见,我有模拟[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? } userStoreuserManagerauthenticationManager。如果我单步执行signInManager操作,则Login始终返回result

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

0 个答案:

没有答案