Pregunta

Estoy tratando de aprender pruebas unitarias. Estoy tratando de probar por unidad algunas cosas de Memembership que estoy haciendo en asp.net mvc 1.0. He estado siguiendo un libro sobre MVC y estoy confundido acerca de algunas cosas que espero que alguien pueda aclararme.

Estoy usando Nunit y Moq para mis frameworks.

Pregunta 1:

  public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider provider)
        {
            FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
            Provider = provider ?? Membership.Provider;
        }

Estoy un poco confundido de qué '' ?? '' ¿Nunca lo había visto antes? Como si ni siquiera supiera qué está pasando realmente aquí. Como si pasaran por la interfaz y luego " ?? " marca sucede y hace una nueva FormsAuthenticationWraper?

Pregunta 2.

 public AuthenticationController(): this(null, null)
        {
        }

Sé que este es el constructor predeterminado, pero no estoy seguro de por qué " ;: this (null, null) " está haciendo.

¿Qué está implementando? y a qué se refiere esto también. Y además, ¿por qué no se puede dejar de lado? Y simplemente pegue el constructor predeterminado tal como está.

Pregunta 3.

En el libro (asp.net mvc 1.0 rápidamente) habla sobre cómo sería bastante trabajo implementar el proveedor de Memembership sería mucho trabajo. Entonces usan el marco de maquetas moq para hacer la vida más fácil.

Ahora mi pregunta es que no usan el moq en la "Autenticación de formularios". En cambio, hacen una interfaz

   public interface IFormsAuthentication
        {
            void SetAuthCookie(string userName, bool createPersistentCookie);
            void SignOut();


        }

Luego haz un envoltorio

public class FormsAuthenticationWrapper: IFormsAuthentication     {         public void SetAuthCookie (string userName, bool createPersistentCookie)         {             FormsAuthentication.SetAuthCookie (userName, createPersistentCookie);         }         public void SignOut ()         {             FormsAuthentication.SignOut ();         }

}

Entonces finalmente una propiedad

   public IFormsAuthentication FormsAuth
        {
            get;
            private set;
        }

Donde como con la membresía solo tienen

Proveedor estático público de MembresíaProveedor     {         obtener;         conjunto privado;     }

No estoy seguro de qué cambiar las cosas también. ¿Como qué cambiaría esta línea también?

FormsAuth = formsAuth ?? nuevo FormsAuthenticationWrapper ();

También traté de agregar otro método en la interfaz y el contenedor de autenticación de formularios.

public void RedirectFromLoginPage (string userName, bool createPersistentCookie)             {                 FormsAuthentication.RedirectFromLoginPage (nombre de usuario, createPersistentCookie);             }

Sin embargo, no estoy seguro de lo que está sucediendo, pero mi prueba unitaria siempre falla, no importa lo que intente hacer para solucionarlo.

     public ActionResult Login(string returnUrl, FormCollection form, bool rememberMe)
            {
                LoginValidation loginValidation = new LoginValidation();
                try
                {
                    UpdateModel(loginValidation, form.ToValueProvider());

                }
                catch
                {

                    return View("Login");
                }

                if (ModelState.IsValid == true)
                {

                    bool valid = authenticate.VerifyUser(loginValidation.UserName, loginValidation.Password);

                    if (valid == false)
                    {
                        ModelState.AddModelError("frm_Login", "Either the Password or UserName is invalid");

                    }
                    else if (string.IsNullOrEmpty(returnUrl) == false)
                    {
                        /* if the user has been sent away from a page that requires them to login and they do 
                         * login then redirect them back to this area*/
                        return Redirect(returnUrl);
                    }
                    else
                    {

                       FormsAuth.RedirectFromLoginPage(loginValidation.UserName, rememberMe);
                    }

                }


                return View("Login");


Here is my test

[Prueba]        público vacío Test_If_User_Is_Redirected_Back_To_Page_They_Came_From_After_Login ()        {            System.Diagnostics.Debugger.Break ();

       var formsAuthenticationMock =  new Mock<AuthenticationController.IFormsAuthentication>();

       var membershipMock = new Mock<MembershipProvider>();

       membershipMock.Setup(m => m.ValidateUser("chobo2", "1234567")).Returns(true);


       // Setup controller
       AuthenticationController target = new AuthenticationController(formsAuthenticationMock.Object, membershipMock.Object);


       // Execute
       FormCollection form = new FormCollection();
       form.Add("Username", "chobo2");
       form.Add("password", "1234567");

       ViewResult actual = target.Login(null, form, false) as ViewResult;

       Assert.That(actual.View, Is.EqualTo("home"));
       formsAuthenticationMock.Verify();

   }

Real siempre vuelve a nulo. Intenté ViewResult, RedirectResult y RedirectToRouteResult pero todos vuelven nulos. Así que no estoy seguro de por qué sucede esto, ya que primero me parece extraño que

                       FormsAuth.RedirectFromLoginPage(loginValidation.UserName, rememberMe);

No detiene la vista y comienza a redirigir. Al principio pensé que una vez que llega a esta línea, es como una declaración de devolución y que no se ejecutará ningún otro código, pero este no parece ser el caso, así que no estoy seguro de si este podría ser el problema.

Gracias

¿Fue útil?

Solución

Pregunta 1

El ?? se llama operador de fusión nula , y es una característica muy útil de C # 2.0 en adelante.

En su caso,

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

simplemente significa " asignar formsAuth a FormsAuth a menos que sea nulo, en cuyo caso asigne new FormsAuthenticationWrapper () " ;. Básicamente es una forma de evitar referencias nulas en su código. También puede considerarlo como un acceso directo para la siguiente expresión condicional:

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

Pregunta 2

El uso de this (null, null) se llama encadenamiento de constructores . Todo esto significa que el constructor en la misma clase (por lo tanto, this , en oposición a base para la clase padre) que toma dos parámetros, debe llamarse antes que el cuerpo del constructor se ejecuta.

La sobrecarga de constructores es una práctica común para facilitar al desarrollador la creación de nuevos objetos cuando solo quieren usar las propiedades / configuraciones predeterminadas.

Pregunta 3

Como otros han mencionado, esto realmente pertenece como una pregunta separada. A diferencia de los dos anteriores, es mucho más específico para el contexto / su código, en lugar de las características de lenguaje de C #.

Actualizar

Ok, lo que he hecho ahora es reescribir los dos constructores aquí, ya que creo que ponerlos en otra forma (prácticamente equivalente) podría ser un poco más claro, y probablemente también sea una mejor práctica de diseño. El operador de fusión nula no es necesario aquí.

public AuthenticationController()
    : this(new FormsAuthenticationWrapper(), Membership.Provider)
{
}

public AuthenticationController(IFormsAuthentication formsAuth,
    MembershipProvider provider)
{
    this.FormsAuth = formsAuth;
    this.Provider = provider;
}

En esta forma, debería ser obvio que el constructor que toma dos parámetros simplemente asigna las variables de clase a los valores de los argumentos. El constructor sin parámetros (a menudo llamado el constructor predeterminado ) simplemente crea un nuevo objeto utilizando los objetos predeterminado FormsAuth y Provider , que se especifican mediante encadenamiento de constructores .

Otros consejos

Pregunta 1: ?? es el operador de fusión nulo . Los ?? El operador comprueba si el valor proporcionado en el lado izquierdo de la expresión es nulo y, de ser así, devuelve un valor alternativo indicado por el lado derecho de la expresión.

En su situación, comprueba si formsAuth es nulo y devuelve un nuevo FormsAuthenticationWrapper () si es nulo.

El ?? El operador dice "use esto, a menos que sea nulo, en cuyo caso use esta otra cosa".

Entonces, esta línea de código:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

Es lo mismo que:

if ( formsAuth != null ) FormsAuth = formsAuth
else FormsAuth = new FormsAuthenticationWrapper();

En respuesta a Q2

Está sobrecargando el constructor.

If significa que llamar

Foo() 

es lo mismo que llamar

Foo(null, null)

Pregunta 1: El operador ?? simplemente dice "tome lo que esté a mi izquierda si no es nulo; si es así, tome lo que esté a mi derecha". Entonces su código:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

es equivalente a

if (formsAuth != null) {
    FormsAuth = formsAuth;
} else {
    FormsAuth 0 new FormsAuthenticationWrapper();
}

Pregunta 2: La sintaxis : this (null, null) es la abreviatura de " herencia del constructor " (mi nombre ...) Tu código

public AuthenticationController(): this(null, null)
    {
    }
public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider  provider)
    {
        FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
        Provider = provider ?? Membership.Provider;
    }

es equivalente a

public AuthenticationController()
    {
        FormsAuth = new FormsAuthenticationWrapper();
        Provider = Membership.Provider;
    }
public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider provider)
    {
        FormsAuth = formsAuth;
        Provider = provider;
    }

Pregunta 2

public AuthenticationController(): this(null, null)
{
}

El constructor sin parámetros para AuthenticationController llamará al constructor que toma una IFormsAuthentication y un MembershipProvider, pasando dos valores nulos (esto se hace antes de que se ejecute cualquier código en el bloque de código del constructor sin parámetros). Dado que el constructor de dos argumentos usa el operador de fusión nula (??) para asignar las variables y los argumentos pasados ??son nulos, se usa un nuevo MembershipProvider junto con el objeto Membership.Provider.

Si este constructor no se hubiera definido explícitamente, se habría utilizado el constructor predeterminado sin parámetros. Esto podría conducir a un comportamiento inesperado si se creara un nuevo AuthenticationController (sin pasar ningún argumento al constructor), ya que las variables miembro no se habrían inicializado.

Pregunta 1:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
Provider = provider ?? Membership.Provider;

es igual a:

FormsAuth = (formsAuth == null ? new FormsAuthenticationWrapper() : formsAuth);
Provider = (provider == null ? Membership.Provider : provider);

Pregunta 2:

Es solo pasar nulo a los formularios de constructor de formularios y deuthAuth. No es una buena práctica en mi humilde opinión. Otro constructor sin argumentos sería mejor.

EDITAR : Esto no tiene sentido. Lo siento, tenía prisa y realmente no me di cuenta de que era un constructor que llamaba a otro constructor.

No tengo tiempo para responder la pregunta 3 en este momento, me ocuparé de eso más tarde ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top