views:

340

answers:

7

Hi

I am trying to learn unit testing. I am trying to unit test some Memembership stuff I am making in asp.net mvc 1.0. I been following a book on MVC and I am confused about some stuff that hopefully someone can clear up for me.

I am using Nunit and Moq for my frameworks.

Question 1:

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

I am kinda confused what "??" does I never really seen it before. Like I don't even know whats happening really in here. Like they passin the interface and then "??" mark happens and makes a new FormsAuthenticationWraper is made?

Question 2.

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

I know this is the default constructor but I am not sure why ": this(null,null)" is doing.

Like what is it implementing? and what is this refering too. And on top of it why can't that be just left out? And just stick the default constructor as it is.

Question 3.

In the book(asp.net mvc 1.0 quickly) it talks about how it would be quite a bit of work to implementing the Memembership provider would be alot of work. So they use moq mockup framework to make life easier.

Now my question is they don't use the moq on the "FormsAuthentication". They instead make an interface

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


        }

Then make a wrapper

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

}

Then finally a property

   public IFormsAuthentication FormsAuth
        {
            get;
            private set;
        }

Where as with the membership they only have

public static MembershipProvider Provider { get; private set; }

I am not sure though what to change the stuff too. Like what would I change this line too?

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

I also tried to add another method into the FormsAuthentication Interface and Wrapper.

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

Yet I am not sure what is happening but my unit test always fails does not matter what I try to do to fix it.

     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] public void 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();

   }

Actual always comes back to null. I tried ViewResult, RedirectResult and RedirectToRouteResult but everyone comes back null. So I am not sure why this is happening since I find it weird first that

                       FormsAuth.RedirectFromLoginPage(loginValidation.UserName, rememberMe);

Does not stop the view and starts to redirect. I thought at first once it hits this line it is like a return statement and thats it no other code will be executed but htis does not seem to be the case so I am not sure if this could be the problem.

Thanks

+1  A: 

Question 1: ?? is the null coalescing operator. The ?? operator checks whether the value provided on the left side of the expression is null, and if so it returns an alternate value indicated by the right side of the expression.

In your situation, it checks if formsAuth is null, and returns a new FormsAuthenticationWrapper() if it is null.

Colin Pickard
+1  A: 

The ?? operator is saying "use this, unless it's null, it which case use this other thing".

So, this line of code:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

Is the same as:

if ( formsAuth != null ) FormsAuth = formsAuth
else FormsAuth = new FormsAuthenticationWrapper();
Eric Petroelje
But wouldn't "this()" be the derived class constructor if it existed and not the base class constructor? Where as "base()" be the base class constructor?
kervin
"calling the base class constructor" NO! this() does **NOT** call the base class constructor! base() does that. Please edit and fix.
dss539
Eric Petroelje
+10  A: 

Question 1

The ?? is called the null-coalescing operator, and is a very useful feature of C# 2.0 onwards.

In your case,

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

simply means "assign formsAuth to FormsAuth unless it is null, in which case assign new FormsAuthenticationWrapper()". It's basically a way of preventing null references in your code. You can also think of it as a shortcut for the following conditional expression:

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

Question 2

The use of this(null, null) is called constructor chaining. All this means is that that the constructor in the same class (hence this, as opposed to base for the parent class) that takes two parameters, should be called before the body of the constructor is executed.

Overloading constructors is a common practice to make it easier for the developer to create new objects when they just want to use the default properties/settings.

Question 3

As others have mentioned, this really belongs as a separate question. Unlike the previous two, it's much more specific to the context/your code, rather than language features of C#.

Update

Ok, what I've done now is actually rewritten the two constructors here, since I think putting them in another (virtually equivalent) form might be a bit clearer, and is probably better design practice too. The null coalescing operator isn't necessary here.

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

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

In this form, it should be obvious that the constructor that takes two parameters simply assigns the class variables to the values of the arguments. The parameterless constructor (often called the default constructor) simply creates a new object using the default FormsAuth and Provider objects, which are specified via constructor chaining.

Noldorin
Hmm ok it is starting to make more sense. With the default constructor one it is inheriting stuff from the controller right?(I am not sure what exactly is being inherited though).I don't know if I could have ever though to do this stuff in a million years lol.I am still wondering when would the case be that formsAuth would be null? I am not seeing that.I will also post a new question for question 3
chobo2
@chobo2: See my updated post.
Noldorin
A: 

In answer to Q2

It is overloading the constructor.

If means that calling

Foo()

is the same as calling

Foo(null, null)
John Nolan
A: 

Question 1:

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

is equals to:

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

Question 2:

It's just passing null to both formsAuth and provider constructor arguments. It's not good practice IMHO. Another constructor with no arguments would be a better fit.

EDIT: This makes no sense. Sorry, I was in a hurry and didn't really realize it was a constructor calling another constructor.

I don't have time to answer question 3 right now, I'll get to that later...

João Marcus
Your answer to question 2 is slightly off - it's not *only* the same as adding another constructor. When you chain the constructors, as in the OP's examples, *both* constructors are actually executed. In this case, one of them just happens to be empty...
Tomas Lycken
"It's not good practice" because... ?
dss539
A: 

Question 1: The ?? operator simply says "take whatever is on my left if it's not null - if it is, take whatever is on my right". So your code:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

is equivalent to

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

Question 2: The :this(null, null) syntax is shorthand for "constructor inheritance" (my naming...). Your code

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

is equivalent to

public AuthenticationController()
    {
        FormsAuth = new FormsAuthenticationWrapper();
        Provider = Membership.Provider;
    }
public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider provider)
    {
        FormsAuth = formsAuth;
        Provider = provider;
    }
Tomas Lycken
ic hmm I sort of like your way better it makes more sense off the bat and does the same thing right?
chobo2
As you can see in Noldorin's answer, the examples for question 2 are only equivalent in this specific example, but not by necessity.
Tomas Lycken
A: 

Question 2

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

The no parameter constructor for AuthenticationController will call the constructor that takes a IFormsAuthentication and a MembershipProvider, passing two null values (this is done before any code in the no-param constructor code block is executed). Since the two argument constructor uses the null-coalescing (??) operator to assign the variables and the passed arguments are null, a new MembershipProvider is used along with Membership.Provider object.

Had this constructor not been explicitly defined, the default no-param constructor would have been used. This could lead to unexpected behaviour if a new AuthenticationController was created (without passing any arguments to the constructor), since the member variables would not have been initialised.

owst