需要帮助理解这段代码

发布于 2024-07-25 14:28:02 字数 4845 浏览 6 评论 0原文

我正在尝试学习单元测试。 我正在尝试对我在 asp.net mvc 1.0 中制作的一些会员资格内容进行单元测试。 我一直在关注一本关于 MVC 的书,我对一些东西感到困惑,希望有人能为我解答。

我的框架使用 Nunit 和 Moq。

问题1:

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

我有点困惑什么是“??” 我以前从未真正见过它吗? 就像我什至不知道这里到底发生了什么。 就像他们传递界面然后“??” 标记发生并使得新的 FormsAuthenticationWraper 被制作?

问题2。

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

我知道这是默认构造函数,但我不确定为什么“: this(null,null)”会这样做。

比如它正在实施什么? 这又指的是什么。 最重要的是,为什么不能把它排除在外呢? 并保持默认构造函数不变。

问题 3.

在本书(asp.net mvc 1.0 快速)中,它讨论了实现 Memembership 提供程序将需要大量工作。 因此他们使用起订量模型框架来让生活更轻松。

现在我的问题是他们不使用“FormsAuthentication”上的最小起订量。 相反,他们创建一个接口

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


        }

然后创建一个包装器

公共类 FormsAuthenticationWrapper : IFormsAuthentication { 公共无效SetAuthCookie(字符串用户名,布尔createPersistentCookie) { FormsAuthentication.SetAuthCookie(用户名, createPersistentCookie); } 公共无效注销() { FormsAuthentication.SignOut(); ,

}

最后是一个属性

   public IFormsAuthentication FormsAuth
        {
            get;
            private set;
        }

与成员资格一样,他们只有

public static MembershipProvider Provider { 得到; 私人套装; 我也不

确定要改变什么。 比如我也会改变这条线吗?

表单验证 = 表单验证 ?? 新的 FormsAuthenticationWrapper();

我还尝试在 FormsAuthentication 接口和包装器中添加另一种方法。

公共无效RedirectFromLoginPage(字符串用户名,布尔createPersistentCookie) { FormsAuthentication.RedirectFromLoginPage(userName, createPersistentCookie); 然而

我不确定发生了什么,但我的单元测试总是失败,无论我尝试做什么来修复它。

     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_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();

   }

实际总是回到零。 我尝试了 ViewResult、RedirectResult 和 RedirectToRouteResult 但每个人都返回 null。 所以我不确定为什么会发生这种情况,因为我首先发现它很奇怪,

                       FormsAuth.RedirectFromLoginPage(loginValidation.UserName, rememberMe);

不停止视图并开始重定向。 我一开始以为一旦它击中这一行,它就像一个 return 语句,并且不会执行其他代码,但情况似乎并非如此,所以我不确定这是否可能是问题所在。

谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

无人接听 2024-08-01 14:28:02

问题 1

?? 称为 空合并运算符,是 C# 2.0 及以后版本中非常有用的功能。

在您的情况下,

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

仅意味着“将 formsAuth 分配给 FormsAuth,除非它为空,在这种情况下分配 new FormsAuthenticationWrapper()”。 它基本上是防止代码中出现空引用的一种方法。 您也可以将其视为以下条件表达式的快捷方式:

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

问题 2

this(null, null) 的使用称为 构造函数链。 所有这一切意味着,同一个类中带有两个参数的构造函数(因此是 this,而不是父类的 base),应该在主体之前调用构造函数的执行。

重载构造函数是一种常见的做法,可以让开发人员在只想使用默认属性/设置时更轻松地创建新对象。

问题 3

正如其他人提到的,这确实属于一个单独的问题。 与前两者不同,它更具体于上下文/代码,而不是 C# 的语言功能。

更新

好吧,我现在所做的实际上是在这里重写了两个构造函数,因为我认为将它们放在另一种(几乎等效的)形式中可能会更清晰一些,并且可能也是更好的设计实践。 这里不需要空合并运算符。

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

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

在这种形式中,很明显,带有两个参数的构造函数只是将类变量分配给参数的值。 无参数构造函数(通常称为默认构造函数)只是使用默认FormsAuthProvider对象创建一个新对象,它们是通过构造函数链指定的。

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.

太阳男子 2024-08-01 14:28:02

问题一:?? 是 空合并运算符。 这 ?? 运算符检查表达式左侧提供的值是否为空,如果是,则返回表达式右侧指示的替代值。

在您的情况下,它检查 formsAuth 是否为 null,如果为 null,则返回一个新的 FormsAuthenticationWrapper() 。

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.

自由如风 2024-08-01 14:28:02

这 ?? 运算符说“使用这个,除非它为空,否则使用其他东西”。

所以,这行代码:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

等同于:

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

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();
×眷恋的温暖 2024-08-01 14:28:02

回答 Q2

它正在重载构造函数。

if 表示调用

Foo() 

与调用相同

Foo(null, null)

In answer to Q2

It is overloading the constructor.

If means that calling

Foo() 

is the same as calling

Foo(null, null)
瑕疵 2024-08-01 14:28:02

问题 1:
?? 运算符只是说“如果不为空,则取我左边的任何内容 - 如果为空,则取我右边的任何内容”。 所以你的代码:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

相当于

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

问题2: :this(null, null) 语法是“构造函数继承”的简写(我的命名...)。 你的代码

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

相当于

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

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;
    }
娇纵 2024-08-01 14:28:02

问题 2

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

AuthenticationController 的无参数构造函数将调用采用 IFormsAuthentication 和 MembershipProvider 的构造函数,并传递两个 null 值(这是在执行无参数构造函数代码块中的任何代码之前完成的)。
由于两个参数构造函数使用 null 合并 (??) 运算符来分配变量并且传递的参数为 null,因此将使用新的 MembershipProvider 和 Membership.Provider 对象。

如果未显式定义此构造函数,则将使用默认的无参数构造函数。 如果创建新的 AuthenticationController (未将任何参数传递给构造函数),这可能会导致意外行为,因为成员变量尚未初始化。

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.

几味少女 2024-08-01 14:28:02

问题 1:

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

等于:

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

问题 2:

它只是将 null 传递给 formsAuth 和提供者构造函数参数。 恕我直言,这不是一个好的做法。 另一个不带参数的构造函数会更合适。

编辑:这没有意义。 抱歉,我很着急,并没有真正意识到这是一个构造函数调用另一个构造函数。

我现在没有时间回答问题3,稍后我会回答...

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文