2012-03-21 25 views
8

Soy bastante nuevo en las pruebas unitarias y conceptos falsos. Estoy tratando de encontrar la manera de escribir un buen caso de prueba para la básica fuera del código de registro de usuario caja de abajo:ASP .Net MVC 3: Acciones del controlador de prueba unitaria

:

[HttpPost] 
public ActionResult Register(RegisterModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     // Attempt to register the user 
     MembershipCreateStatus createStatus; 
     Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus); 

     if (createStatus == MembershipCreateStatus.Success) 
     { 
      FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */); 
      return RedirectToAction("Index", "Home"); 
     } 
     else 
     { 
      ModelState.AddModelError("", ErrorCodeToString(createStatus)); 
     } 
    } 

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

A continuación se presentan algunos de los puntos específicos donde necesito su opinión/ayuda

  1. No necesariamente quiero crear un nuevo usuario en la base de datos de miembros de ASP .Net.
  2. Basado en el modelo pasado, ¿cómo realmente me aseguro de que si el usuario se registró correctamente o hubo errores en el proceso.

Respuesta

25

Tiene un problema con su código. Su acción depende de un método estático: Membership.CreateUser. Y como sabe, los métodos estáticos son PITA para la prueba unitaria.

por lo que podría debilitar el acoplamiento mediante la introducción de un nivel de abstracción:

public interface IMyService 
{ 
    MembershipCreateStatus CreateUser(string username, string password, string email); 
} 

y luego tener alguna aplicación que utilice el proveedor de pertenencia actual:

public class MyService: IMyService 
{ 
    public MembershipCreateStatus CreateUser(string username, string password, string email) 
    { 
     MembershipCreateStatus status; 
      Membership.CreateUser(username, password, email, null, null, true, null, out status); 
     return status; 
    } 
} 

y, finalmente, el controlador:

public class AccountController : Controller 
{ 
    private readonly IMyService _service; 
    public AccountController(IMyService service) 
    { 
     _service = service; 
    } 

    [HttpPost] 
    public ActionResult Register(RegisterModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      // Attempt to register the user 
      var status = _service.CreateUser(model.UserName, model.Password, model.Email); 
      if (status == MembershipCreateStatus.Success) 
      { 
       FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */); 
       return RedirectToAction("Index", "Home"); 
      } 
      else 
      { 
       ModelState.AddModelError("", ErrorCodeToString(createStatus)); 
      } 
     } 

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

OK, ahora que hemos debilitado el acoplamiento podríamos Es un marco burlón para burlarse del servicio en la prueba unitaria y hacerlo trivial.

Por ejemplo, usando burla de Rhino puede crear las siguientes pruebas para cubrir los casos de falla 2:

[TestMethod] 
public void Register_Action_Should_Redisplay_View_If_Model_Is_Invalid()  
{ 
    // arrange 
    var sut = new AccountController(null); 
    var model = new RegisterModel(); 
    sut.ModelState.AddModelError("", "invalid email"); 

    // act 
    var actual = sut.Register(model); 

    // assert 
    Assert.IsInstanceOfType(actual, typeof(ViewResult)); 
    var viewResult = actual as ViewResult; 
    Assert.AreEqual(model, viewResult.Model); 
} 

[TestMethod] 
public void Register_Action_Should_Redisplay_View_And_Add_Model_Error_If_Creation_Fails() 
{ 
    // arrange 
    var service = MockRepository.GenerateStub<IMyService>(); 
    service 
     .Stub(x => x.CreateUser(null, null, null)) 
     .IgnoreArguments() 
     .Return(MembershipCreateStatus.InvalidEmail); 
    var sut = new AccountController(service); 
    var model = new RegisterModel(); 

    // act 
    var actual = sut.Register(model); 

    // assert 
    Assert.IsInstanceOfType(actual, typeof(ViewResult)); 
    var viewResult = actual as ViewResult; 
    Assert.AreEqual(model, viewResult.Model); 
    Assert.IsFalse(sut.ModelState.IsValid); 
} 

La prueba final es el caso de éxito. Todavía tenemos un problema con eso. El problema es la siguiente línea:

FormsAuthentication.SetAuthCookie(model.UserName, false); 

¿Qué es esto? Es una llamada de método estático. Entonces procedemos de la misma manera que lo hicimos con el proveedor de membresía para debilitar el acoplamiento de nuestro controlador y el sistema de autenticación de formularios.

+4

+1 para un recorrido fácil y fácil de seguir. – ljubomir

0

Para probar este método se puede seguir dos vías

  1. Dentro de la clase de prueba crear una nueva clase que hereda de la clase Membership y reemplazar el método CreateUser.
  2. Usa Moq para burlarte de la clase.

Para el primer caso comprobaré si el nombre de usuario es igual a "GoodUser" o "BadUser" y genera un MembershipCreateStatus.Success o un estado diferente.

Por el momento configuraré dos métodos que siguen la misma idea que en el otro método. Vea esto link para un ejemplo

Cuestiones relacionadas