简体   繁体   中英

Unit Test for login in asp.net mvc 3

I have a problem testing a logon method using existing AccountController (made by MVC)...

I have this simple test method:

  [TestMethod]
  public void LogOnTest1() {
     AccountController controller = new AccountController();

     LogOnModel logonModel = new LogOnModel();
     logonModel.UserName = "test";
     logonModel.Password = "test1234";

     if ( controller.MembershipService == null ) {
        controller.MembershipService = new AccountMembershipService();
     }

     if ( controller.FormsService == null ) {
        controller.FormsService = new FormsAuthenticationService();
     }

     var result = controller.LogOn( logonModel, "" ) as ViewResult;

     Assert.AreEqual( "Index", result.ViewName );
  }

and the method defined in AccountController :

[HttpPost]
      public ActionResult LogOn( LogOnModel model, string returnUrl ) {
         if ( ModelState.IsValid ) {
            if ( MembershipService.ValidateUser( model.UserName, model.Password ) ) {
               FormsService.SignIn( model.UserName, model.RememberMe );
               if ( !string.IsNullOrEmpty( returnUrl ) ) {
                  return Redirect( returnUrl );
               } else {
                  return RedirectToAction( "Index", "Home" );
               }
            } else {
               ModelState.AddModelError( "", "The user name or password provided is incorrect." );
            }
         }

         // If we got this far, something failed, redisplay form
         return View( model );
      }

The above method is not defined/modified by me. Just created by when create an asp.net mvc project.

The problem is at line

if ( MembershipService.ValidateUser( model.UserName,model.Password ) ) {

which returns always false though I provided correct login info.

Where is my mistake ?

First of all, do not use if statements and other conditional logic in your tests. Also do not use concrete classes in your tests. If this test will fail, how will you know why? What was broken - controller or AccountMembershipService ? Use abstract dependencies, which could be mocked.

public class AccountController : Controller
{
    private IMembershipService _membershipService;
    private IFormsService _formsService;

    public AccountController(IMembershipService membershipService,
                             IFormsService formsService)
    {
        _membershipService = membershipService;
        _formsService = formsService;
    }

    public ActionResult LogOn(LogOnModel model, string returnUrl)
    {
        // implementation goes here
    }
}

And your tests:

[Test]
public void ShouldNotAcceptInvalidUser()
{
    // Arrange
    Mock<IMembershipService> membership = new Mock<IMembershipService>();
    membership.Setup(m => m.ValidateUser(It.IsAny<string>(), It.IsAny<string>()))
              .Returns(false);
    Mock<IFormsService> forms = new Mock<IFormsService>();
    var logonModel = new LogOnModel() { UserName = "", Password = "" };
    var controller = new AccountController(membership.Object, forms.Object);

    // Act
    var result = controller.LogOn(logonModel, "") as ViewResult;

    // Assert
    Assert.That(result.ViewName, Is.EqualTo("Index"));
    Assert.False(controller.ModelState.IsValid);
    Assert.That(controller.ModelState[""], 
                Is.EqualTo("The user name or password provided is incorrect."));
}

Interesting here is that you don't care which logon info you passed to controller. You mock response from membership service, which says logon was incorrect.

FEW TESTS MORE:

[Test]
public void ShouldRedisplayViewWhenModelIsNotValid()
{
   // Arrange        
   Mock<IMembershipService> membership = new Mock<IMembershipService>();
   Mock<IFormsService> forms = new Mock<IFormsService>();
   var model = new LogOnModel() { UserName = "", Password = "" };
   var controller = new AccountController(membership.Object, forms.Object);
   controller.ModelState.AddModelError("key", "error message");
   // Act
   var result = controller.LogOn(model, "") as ViewResult;
   // Assert
   Assert.That(result.ViewName, Is.EqualTo("LogOn"));
}

[Test]
public void ShouldSignInAndRedirectToIndex()
{
   // Arrange        
   Mock<IMembershipService> membership = new Mock<IMembershipService>();
  membership.Setup(m => m.ValidateUser(It.IsAny<string>(), It.IsAny<string>()))
             .Returns(true);
   Mock<IFormsService> forms = new Mock<IFormsService>();
   var model = new LogOnModel() { UserName = "", Password = "" };
   var controller = new AccountController(membership.Object, forms.Object);
   controller.ModelState.AddModelError("key", "error message");
   // Act
   var result = controller.LogOn(model, "") as ViewResult;

   // Assert
   forms.Verify(f => f.SignIn(model.UserName, model.RememberMe));
   Assert.That(result.ViewName, Is.EqualTo("Index"));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM