TDD 和受保护的方法
TDD and Protected Methods
我正在尝试通过创建现有 MVC 应用程序的副本来学习 TDD,但我正在使用 TDD 从头开始创建它的副本。
在我现有的应用程序中,我有一个 Application_AuthenticateRequest 方法,如下所示。
这是受保护的。我认为不应测试这些方法是否正确 - 即您应该只测试 public 方法而不是私有和受保护的方法。如果这是真的,那么我会在下面编写我的受保护方法而不为其编写任何测试吗?
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
StaticDataSeeder.Seed();
}
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null) return;
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket == null) return;
var userData = new UserDataModel(authTicket.UserData);
var userPrincipal = new PaxiumPrincipal(new GenericIdentity(authTicket.Name), null)
{
Email = userData.Email,
Menu = userData.Menu,
RememberMe = userData.RememberMe
};
Context.User = userPrincipal;
}
}
仅仅进行测试并不能使其成为 TDD。如果您已经假设私有方法可以做某事,那么开发不是由测试驱动的,对吗?
试着先盲目地编写测试,你可能最终根本不需要私有方法,甚至可能将它作为另一个 class.
中的 public 方法
是的,你的测试用例是正确的,你只能测试你可以调用的方法。所以通常 public 方法是可测试的。同样,如果您的组件中有私有方法,则意味着它必须由该组件中的至少一个 public 方法调用。因此,当您测试 public 方法时,您也在同一个测试中测试私有方法的功能。您可以将私有方法视为 public 方法的几行,将 public 方法排除在外,使代码更具可读性和可重用性。
受保护的方法在您正在创建的 class 和它的未来子项之间创建契约。如果您不想创建此合同,则可以将这些方法定义为私有的,而不是受保护的。因此,我认为您应该测试这些方法的行为是否符合任何派生 classes 所期望的期望。
考虑两个 classes:
public abstract class BaseMathsClass {
protected int Mult(int a, int b) {
return a * b;
}
}
public class ConcreteMathClass : BaseMathsClass {
public int Square(int x) {
return Mult(x, x);
}
}
如果您乐于在 ConcreteMathClass
的测试中测试 Mult
方法的功能,那么您不需要为基础 class 编写测试。但是,如果您确实为基础 class 编写测试,这会在编写基础 class 时巩固合同,并且意味着任何派生的 classes 都知道他们正在签署什么起来。你站在栅栏的哪一边,取决于你的意见。 This question有一些其他意见。
你还说你认为你不需要测试私有方法。这是真的,因为您不需要编写特定的测试来直接调用私有方法,但是您应该通过针对 class 的 public 方法的测试隐式测试任何私有方法的功能.编写测试时,您不必真正关心 class 是否具有以下任一实现:
实施 1
class MyClass {
public int GetSquare(int someValue) {
return someValue * someValue;
}
}
实施 2
class MyClass {
public int GetSquare(int someValue) {
return Mult(someValue, someValue);
}
private int Mult(int a, int b) {
return a * b;
}
}
使用 实现 2,您不需要编写专门调用 Mult
的测试,GetSquare
的测试足以练习此代码。这并不意味着您只需编写另一个私有方法 Add
,因为目前您的 public 接口上不需要它。
您可能也对 this question 的答案感兴趣。
我正在尝试通过创建现有 MVC 应用程序的副本来学习 TDD,但我正在使用 TDD 从头开始创建它的副本。
在我现有的应用程序中,我有一个 Application_AuthenticateRequest 方法,如下所示。
这是受保护的。我认为不应测试这些方法是否正确 - 即您应该只测试 public 方法而不是私有和受保护的方法。如果这是真的,那么我会在下面编写我的受保护方法而不为其编写任何测试吗?
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
StaticDataSeeder.Seed();
}
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null) return;
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket == null) return;
var userData = new UserDataModel(authTicket.UserData);
var userPrincipal = new PaxiumPrincipal(new GenericIdentity(authTicket.Name), null)
{
Email = userData.Email,
Menu = userData.Menu,
RememberMe = userData.RememberMe
};
Context.User = userPrincipal;
}
}
仅仅进行测试并不能使其成为 TDD。如果您已经假设私有方法可以做某事,那么开发不是由测试驱动的,对吗?
试着先盲目地编写测试,你可能最终根本不需要私有方法,甚至可能将它作为另一个 class.
中的 public 方法是的,你的测试用例是正确的,你只能测试你可以调用的方法。所以通常 public 方法是可测试的。同样,如果您的组件中有私有方法,则意味着它必须由该组件中的至少一个 public 方法调用。因此,当您测试 public 方法时,您也在同一个测试中测试私有方法的功能。您可以将私有方法视为 public 方法的几行,将 public 方法排除在外,使代码更具可读性和可重用性。
受保护的方法在您正在创建的 class 和它的未来子项之间创建契约。如果您不想创建此合同,则可以将这些方法定义为私有的,而不是受保护的。因此,我认为您应该测试这些方法的行为是否符合任何派生 classes 所期望的期望。
考虑两个 classes:
public abstract class BaseMathsClass {
protected int Mult(int a, int b) {
return a * b;
}
}
public class ConcreteMathClass : BaseMathsClass {
public int Square(int x) {
return Mult(x, x);
}
}
如果您乐于在 ConcreteMathClass
的测试中测试 Mult
方法的功能,那么您不需要为基础 class 编写测试。但是,如果您确实为基础 class 编写测试,这会在编写基础 class 时巩固合同,并且意味着任何派生的 classes 都知道他们正在签署什么起来。你站在栅栏的哪一边,取决于你的意见。 This question有一些其他意见。
你还说你认为你不需要测试私有方法。这是真的,因为您不需要编写特定的测试来直接调用私有方法,但是您应该通过针对 class 的 public 方法的测试隐式测试任何私有方法的功能.编写测试时,您不必真正关心 class 是否具有以下任一实现:
实施 1
class MyClass {
public int GetSquare(int someValue) {
return someValue * someValue;
}
}
实施 2
class MyClass {
public int GetSquare(int someValue) {
return Mult(someValue, someValue);
}
private int Mult(int a, int b) {
return a * b;
}
}
使用 实现 2,您不需要编写专门调用 Mult
的测试,GetSquare
的测试足以练习此代码。这并不意味着您只需编写另一个私有方法 Add
,因为目前您的 public 接口上不需要它。
您可能也对 this question 的答案感兴趣。