Need Help understanding this code
我正在努力学习单元测试。我正在尝试对我在ASP.NET MVC 1.0中制作的一些membership进行单元测试。我在看一本关于MVC的书,我对一些希望有人能帮我解决的事情感到困惑。
我正在使用nunit和moq作为框架。
问题1:
1 2 3 4 5 | public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider provider) { FormsAuth = formsAuth ?? new FormsAuthenticationWrapper(); Provider = provider ?? Membership.Provider; } |
我有点困惑什么?"我以前真的没见过吗?好像我都不知道这里到底发生了什么。就像他们通过接口然后??"Mark发生并生成一个新的窗体。是否制作身份验证包装纸?
问题2。
1 2 3 | public AuthenticationController(): this(null, null) { } |
我知道这是默认的构造函数,但我不知道为什么:这个(空,空)正在这样做。
比如它是在实现什么?这也是什么意思。最重要的是,为什么不能把它忽略掉呢?只需按原样粘贴默认的构造函数。
问题3。
在这本书中(ASP.NET MVC 1.0很快),它讨论了实现membership提供程序需要多少工作。所以他们使用moq模型框架来简化生活。
现在我的问题是,他们没有在"形式认证"上使用MOQ。相反,它们形成了一个接口
1 2 3 4 5 6 7 | public interface IFormsAuthentication { void SetAuthCookie(string userName, bool createPersistentCookie); void SignOut(); } |
然后做个包装纸
公共类FormsAuthenticationWrapper:IFormsAuthentication{public void setauthcookie(字符串用户名,bool createpsistentcookie){formsAuthentication.setAuthcookie(用户名,createPersistentcookie);}公共注销()){formsAuthentication.signout();}
1 | } |
最后一个属性
1 2 3 4 5 | public IFormsAuthentication FormsAuth { get; private set; } |
他们只拥有会员资格
公共静态成员身份提供程序{得到;私人集合;}
我也不知道该怎么改变这些东西。我也要换这条线吗?
formsauth=formsauth??新的FormsAuthenticationWrapper();
我还尝试将另一个方法添加到FormsAuthentication接口和包装器中。
public void redirectFromLoginPage(字符串用户名,bool createpsistentcookie){FormsAuthentication.RedirectFromLoginPage(用户名,CreatePersistentCookie);}
然而,我不确定发生了什么,但是我的单元测试总是失败,不管我试图做什么来修复它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 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 |
[试验]公共无效测试如果用户被重定向回页面,他们会在登录后从页面返回{system.diagnostics.debugger.break();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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和redirectoroutereult,但每个人都返回空值。所以我不知道为什么会发生这样的事,因为我首先觉得很奇怪
1 | FormsAuth.RedirectFromLoginPage(loginValidation.UserName, rememberMe); |
不会停止视图并开始重定向。我起初认为,一旦它到达这一行,它就像一个返回语句,因此不会执行其他代码,但HTIS似乎不是这样,所以我不确定这是否是问题所在。
谢谢
问题1
在你的情况下,
1 | FormsAuth = formsAuth ?? new FormsAuthenticationWrapper(); |
简单的意思是"将
1 | FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper(); |
问题2
使用
重载构造函数是一种常见的实践,它使开发人员在只想使用默认属性/设置时更容易创建新对象。
问题3正如其他人提到的,这确实是一个单独的问题。与前两个不同,它更具体地针对上下文/您的代码,而不是C的语言特性。
更新好的,我现在所做的实际上是重写这里的两个构造函数,因为我认为将它们放在另一个(实际上等价的)形式中可能会更清楚一些,而且可能也是更好的设计实践。这里不需要空合并运算符。
1 2 3 4 5 6 7 8 9 10 11 | public AuthenticationController() : this(new FormsAuthenticationWrapper(), Membership.Provider) { } public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider provider) { this.FormsAuth = formsAuth; this.Provider = provider; } |
在这种形式中,显然采用两个参数的构造函数只是将类变量分配给参数的值。无参数构造器(通常称为默认构造器)只使用默认的
这个??操作员说"使用这个,除非它是空的,在这种情况下使用另一个东西"。
所以,这一行代码:
1 | FormsAuth = formsAuth ?? new FormsAuthenticationWrapper(); |
相同:
1 2 | if ( formsAuth != null ) FormsAuth = formsAuth else FormsAuth = new FormsAuthenticationWrapper(); |
问题1:??是空合并运算符。这个??运算符检查表达式左侧提供的值是否为空,如果为空,则返回表达式右侧指示的备用值。
在您的情况下,它检查
问题2
1 2 3 | public AuthenticationController(): this(null, null) { } |
authenticationController的无参数构造函数将调用采用iformsAuthentication和membershipProvider的构造函数,并传递两个空值(这是在执行无参数构造函数代码块中的任何代码之前完成的)。因为两个参数的构造函数使用了空合并(??)用于分配变量的运算符,传递的参数为空,新的MembershipProvider与Membership.Provider对象一起使用。
如果没有显式定义此构造函数,则不会使用默认的无参数构造函数。如果创建了新的authenticationController(不向构造函数传递任何参数),这可能会导致意外的行为,因为成员变量不会被初始化。
问题1:
1 | FormsAuth = formsAuth ?? new FormsAuthenticationWrapper(); |
等于
1 2 3 4 5 | if (formsAuth != null) { FormsAuth = formsAuth; } else { FormsAuth 0 new FormsAuthenticationWrapper(); } |
问题2:
1 2 3 4 5 6 7 8 | public AuthenticationController(): this(null, null) { } public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider provider) { FormsAuth = formsAuth ?? new FormsAuthenticationWrapper(); Provider = provider ?? Membership.Provider; } |
等于
1 2 3 4 5 6 7 8 9 10 | public AuthenticationController() { FormsAuth = new FormsAuthenticationWrapper(); Provider = Membership.Provider; } public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider provider) { FormsAuth = formsAuth; Provider = provider; } |
问题1:
1 2 | FormsAuth = formsAuth ?? new FormsAuthenticationWrapper(); Provider = provider ?? Membership.Provider; |
等于:
1 2 | FormsAuth = (formsAuth == null ? new FormsAuthenticationWrapper() : formsAuth); Provider = (provider == null ? Membership.Provider : provider); |
问题2:
它只是将空值传递给formsauth和provider构造函数参数。这不是很好的练习。另一个没有参数的构造函数会更适合。
编辑:这没有意义。抱歉,我当时很着急,没有真正意识到它是一个调用另一个构造函数的构造函数。
我现在没有时间回答第三个问题,稍后再谈……
回答Q2
它正在重载构造函数。
如果意味着打电话
1 | Foo() |
和打电话一样吗
1 | Foo(null, null) |