Question

J'essaie d'apprendre les tests unitaires. J'essaie de tester à l'unité certains éléments de Memembership que je réalise dans asp.net mvc 1.0. J'ai suivi un livre sur MVC et je suis confus au sujet de choses qui, espérons-le, pourront être éclaircies par moi.

J'utilise Nunit et Moq pour mes frameworks.

Question 1:

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

Je suis un peu confus sur ce que "??". Est-ce que je ne l'ai jamais vraiment vu auparavant? Comme je ne sais même pas ce qui se passe vraiment ici. Comme s'ils passaient par l'interface puis "??" marque arrive et fait un nouveau FormsAuthenticationWraper est faite?

Question 2.

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

Je sais que c'est le constructeur par défaut, mais je ne suis pas sûr de savoir pourquoi ": this (null, null) " est en train de faire.

Comme quoi cela est-il mis en œuvre? et quelle est cette référence aussi. Et en plus, pourquoi ne peut-on pas laisser cela de côté? Et collez simplement le constructeur par défaut tel quel.

Question 3.

Dans le livre (asp.net mvc 1.0 rapidement), il est expliqué que la mise en oeuvre du fournisseur Memembership demanderait beaucoup de travail. Ils utilisent donc le framework moq mockup pour faciliter la vie.

Maintenant, ma question est qu'ils n'utilisent pas le moq sur "FormsAuthentication". Au lieu de cela, ils font une interface

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


        }

Créez ensuite un wrapper

Classe publique FormsAuthenticationWrapper: IFormsAuthentication     {         public void SetAuthCookie (string userName, bool createPersistentCookie)         {             FormsAuthentication.SetAuthCookie (nom d'utilisateur, createPersistentCookie);         }         vide public SignOut ()         {             FormsAuthentication.SignOut ();         }

}

Puis finalement une propriété

   public IFormsAuthentication FormsAuth
        {
            get;
            private set;
        }

Où, comme pour les membres, ils n’ont que

public static MembershipProvider Provider     {         obtenir;         ensemble privé;     }

Je ne sais pas trop quoi changer. Comme qu'est-ce que je changerais aussi cette ligne?

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper ();

J'ai également essayé d'ajouter une autre méthode à l'interface et au wrapper de FormsAuthentication.

public void RedirectFromLoginPage (chaîne userName, bool createPersistentCookie)             {                 FormsAuthentication.RedirectFromLoginPage (userName, createPersistentCookie);             }

Pourtant, je ne suis pas sûr de ce qui se passe mais mon test unitaire échoue toujours, peu importe ce que j'essaie de faire pour le réparer.

     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

[Test]        annulation publique 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();

   }

Réel revient toujours à null. J'ai essayé ViewResult, RedirectResult et RedirectToRouteResult mais tout le monde revient nul. Donc, je ne sais pas pourquoi cela se produit depuis que je trouve ça bizarre d'abord que

                       FormsAuth.RedirectFromLoginPage(loginValidation.UserName, rememberMe);

N'arrête pas la vue et commence à rediriger. J'ai d'abord pensé qu'une fois que cette ligne apparaissait sur cette ligne, elle ressemblait à une instruction return et qu'aucun autre code ne serait exécuté, mais que cela ne semble pas être le cas, je ne suis pas sûr que cela puisse être le problème.

Merci

Était-ce utile?

La solution

Question 1

Le ?? est appelé opérateur null-coalescing , qui est une fonctionnalité très utile à partir de C # 2.0.

Dans votre cas,

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

signifie simplement "attribuer formsAuth à FormsAuth sauf si elle est nulle, auquel cas attribuer new FormsAuthenticationWrapper () .". C'est fondamentalement un moyen d'empêcher les références nulles dans votre code. Vous pouvez également y voir un raccourci pour l'expression conditionnelle suivante:

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

Question 2

L'utilisation de this (null, null) est appelée Chaîne de constructeurs . Cela signifie simplement que le constructeur de la même classe (d'où this , par opposition à base pour la classe parent) prenant deux paramètres, doit être appelé avant le corps du constructeur est exécuté.

La surcharge des constructeurs est une pratique courante qui permet au développeur de créer plus facilement de nouveaux objets lorsqu'il souhaite simplement utiliser les propriétés / paramètres par défaut.

Question 3

Comme d’autres l’ont déjà mentionné, cette question relève vraiment de la question distincte. Contrairement aux deux précédents, il est beaucoup plus spécifique au contexte / à votre code plutôt qu’aux fonctionnalités de langage de C #.

Mettre à jour

Ok, ce que je viens de faire est en fait de réécrire les deux constructeurs ici, car je pense que les mettre sous une autre forme (pratiquement équivalente) pourrait être un peu plus clair, et constitue probablement une meilleure pratique en matière de conception. L'opérateur de fusion nul n'est pas nécessaire ici.

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

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

Sous cette forme, il devrait être évident que le constructeur qui prend deux paramètres affecte simplement les variables de classe aux valeurs des arguments. Le constructeur sans paramètre (souvent appelé constructeur default ) crée simplement un nouvel objet à l'aide des objets default FormsAuth et Fournisseur , qui sont spécifiés via le constructeur chaînage .

Autres conseils

Question 1: ?? est le opérateur de coalescence nul . Le ?? L'opérateur vérifie si la valeur fournie à gauche de l'expression est null et renvoie, le cas échéant, une autre valeur indiquée par le côté droit de l'expression.

Dans votre cas, il vérifie si formsAuth est null et renvoie un nouveau FormsAuthenticationWrapper () s'il est null.

Le ?? L’opérateur dit "utilisez ceci, à moins que ce ne soit null, il utilisera cette autre chose".

Donc, cette ligne de code:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

est identique à:

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

En réponse à la Q2

Il surcharge le constructeur.

Si signifie que l'appelant

Foo() 

équivaut à appeler

Foo(null, null)

Question 1: L'opérateur ?? dit simplement "prenez tout ce qui se trouve à gauche si ce n'est pas nul - si c'est le cas, prenez tout ce qui se trouve à ma droite". Donc, votre code:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

est équivalent à

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

Question 2: le : cette syntaxe (null, null) est un raccourci pour "héritage du constructeur". (mon nom ...). Votre code

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

est équivalent à

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

Question 2

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

Le constructeur no paramètre pour AuthenticationController appellera le constructeur qui prend un IFormsAuthentication et un MembershipProvider, en transmettant deux valeurs null (ceci est fait avant que tout code du bloc de code constructeur no-param soit exécuté). Étant donné que le constructeur à deux arguments utilise l'opérateur null-coalescing (??) pour affecter les variables et que les arguments transmis sont null, un nouveau MembershipProvider est utilisé avec l'objet Membership.Provider.

Si ce constructeur n'avait pas été défini explicitement, le constructeur no-param par défaut aurait été utilisé. Cela pourrait entraîner un comportement inattendu si un nouveau AuthenticationController était créé (sans passer aucun argument au constructeur), car les variables membres n'auraient pas été initialisées.

Question 1:

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

est égal à:

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

Question 2:

Il ne fait que passer null aux arguments du constructeur de formsAuth et du constructeur. Ce n'est pas une bonne pratique à mon humble avis. Un autre constructeur sans argument serait un meilleur ajustement.

EDIT : cela n'a aucun sens. Désolé, j'étais pressé et je n'avais pas vraiment compris qu'il s'agissait d'un constructeur qui appelle un autre constructeur.

Je n'ai pas le temps de répondre à la question 3 maintenant, j'y reviendrai plus tard ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top