【问题标题】:TDD and Protected Methods [duplicate]TDD 和受保护的方法 [重复]
【发布时间】:2015-08-09 01:33:31
【问题描述】:

我正在尝试通过创建现有 MVC 应用程序的副本来学习 TDD,但我正在使用 TDD 从头开始​​创建它的副本。

在我现有的应用程序中,我有一个 Application_AuthenticateRequest 方法,如下所示。

这是受保护的。我认为这些方法不应该被测试是否正确 - 即你应该只测试公共方法而不是私有和受保护的方法。如果这是真的,那么我是否会直接在下面编写受保护的方法而不编写任何测试?

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;
    }
}

【问题讨论】:

  • 我认为您需要阅读此article 它可能对您有用
  • 关于这个问题以前被问过 - 我可以很容易地搜索这个问题,因为我相信这个问题已经在这个网站和许多其他网站上被问过很多次了。不过,我喜欢与人进行对话交流,有时不想只用谷歌搜索——我想要人际互动。
  • 我认为,如果您针对您的具体情况定制了您的问题,那就是您想知道在创建适合现有的类时是否/应该如何使用 TDD生态系统并需要特定的扩展点,因此该问题不太可能作为重复而关闭,并且您将获得更多相关的答案作为起点(例如,当前投票率最高的答案似乎并没有特别解决您的问题似乎已经想到了)。
  • 是的,我想你是对的,我的错。

标签: c# asp.net-mvc tdd


【解决方案1】:

仅进行测试并不能使其成为 TDD。如果您已经假设私有方法可以做某事,那么开发不是由测试驱动的,是吗?

尝试盲目地先编写测试,您最终可能根本不需要私有方法,甚至将其作为另一个类中的公共方法。

【讨论】:

  • 我的代码实际上被挂接到了 MVC 应用程序的管道中——它不是我调用的一些简单的 api。它需要在它的位置,因此我不确定应该如何处理。
【解决方案2】:

是的,您的测试用例是正确的,您只能测试您可以调用的方法。所以通常公共方法是可测试的。同样,如果您的组件中有私有方法,这意味着它必须由该组件中的至少一个公共方法调用。因此,当您测试公共方法时,您也在同一测试中测试私有方法的功能。您可以将私有方法视为公共方法中的几行,使其远离该公共方法,以使代码更具可读性和可重用性。

【讨论】:

  • 我没有调用公共方法 - 它们在 MVC 应用程序的管道中。
  • 如果您想遵循 TDD,您应该编写测试用例来单独测试您的组件的公共方法(模拟必要的依赖项),无论它在您的框架中如何以及在何处使用。
【解决方案3】:

受保护的方法在您正在创建的类和它的未来子类之间创建一个契约。如果您不想创建此合同,您会将这些方法定义为私有的,而不是受保护的。因此,我认为您应该测试这些方法的行为是否符合任何派生类的预期。

考虑两个类:

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 方法的功能,那么您不需要为基类编写测试。但是,如果您确实为基类编写测试,这会在编写基类时巩固合同,并且意味着任何派生类都知道它们要注册的内容。你落在栅栏的哪一边,取决于你的意见。 This question 有其他意见。

你还说你相信你不需要测试私有方法。这是真的,因为您不需要编写特定的测试来直接调用私有方法,但是您应该通过针对类的公共方法的测试来隐式地测试任何私有方法的功能。在编写测试时,您不必真正关心您的类是否具有以下任一实现:

实施 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,因为目前在您的公共接口上不需要它。

您可能还对this question 的答案感兴趣。

【讨论】:

  • 在这种情况下,我没有调用或编写公共方法——它都在 MVC 应用程序的管道中。
  • @DaveAmour 行为仍然需要测试,否则不应该存在。根据方法的作用,您可能会决定就地测试它(在这种情况下通过集成测试)比单独进行单元测试更容易/更合适,这个决定与我上面指出的基本相同您需要决定是否使用受保护的方法测试类,或者您乐于将它们视为更大单元的一部分并通过使用它们的类隐式测试它们。
  • 好的,谢谢 - 这是我正在努力解决的主观决策的灰色地带。真的可以和一些经验丰富的开发人员一起做一些真正的 TDD 工作,但我只需要在家里自己做这一切。
  • @DaveAmour 即使在优秀的团队中,狂热者和实用主义者之间仍然非常主观。就我个人而言,我认为最好的入门方法是先尝试 100% 测试一段时间,然后研究一些技术以使您的代码更易于单元测试,然后找出对您来说什么构成单元以及何时集成测试更好很长的路要走,所以如果你发现某个地方在做 TDD,那么你就准备好了讨论。我并没有真正使用它,但可能值得看看是否有合适的聊天室来从其他人那里获得一些反馈。
  • 谢谢 - 好建议。我还想在 Application_AuthenticateRequest 中提取我的代码并将其放在一个单独的类中,然后我可以从 Application_AuthenticateRequest 中调用它并单独测试该类(当然还有各种模拟)!
猜你喜欢
  • 2016-07-25
  • 2012-03-27
  • 2014-02-11
  • 2020-03-31
  • 2011-07-09
  • 2011-02-03
  • 1970-01-01
  • 2016-02-19
  • 2015-11-04
相关资源
最近更新 更多