如何使用DUnit测试私有方法?

时间:2009-01-07 22:10:50

标签: delphi unit-testing dunit

我有一个班级,我正在与DUnit进行单元测试。 它有一些方法,一些公共方法和私有方法。

type
  TAuth = class(TDataModule)
  private
    procedure PrivateMethod;
  public
    procedure PublicMethod;
  end;

为了为这个课程编写单元测试,我必须公开所有方法。

是否有不同的方式来声明私有方法,以便我仍然可以测试它们但它们不公开?

7 个答案:

答案 0 :(得分:21)

您不需要公开它们。受保护的人会这样做。然后,您可以对类进行子类型以进行单元测试并显示受保护的方法。例如:

type
  TAuth = class(TDataModule)
  protected
    procedure MethodIWantToUnitTest;
  public
    procedure PublicMethod;
  end;

现在您可以将其子类型用于单元测试:

interface

uses
  TestFramework, Classes, AuthDM;

type
  // Test methods for class TAuthDM
  TestAuthDM = class(TTestCase)
     // stuff
  end;

  TAuthDMTester = class(TAuthDM)
  public
    procedure MethodIWantToUnitTestMadePublic;
  end;

implementation

procedure TAuthDMTester.MethodIWantToUnitTestMadePublic;
begin
  MethodIWantToUnitTest;
end;

但是,如果你想要进行单元测试的方法与数据模块密切相关,除了私有之外它们是不安全的,那么你应该考虑重构这些方法以便分离需要的代码进行单元测试和访问数据模块内部的代码。

答案 1 :(得分:8)

这有点hacky,但我喜欢使用这个条件编译指令:

  {$IfNDef TEST}
  private
  {$EndIf}

您的单元测试项目应在project → conditional defines中定义TEST。

如果没有可见性规范,它们就会发布。注意:如果私有可见性不是类声明中的第一个,它将获得先前的定义。一种更安全的方式,但更详细,更不清楚,将是:

  private
  {$IfDef TEST}
  public
  {$EndIf}

这比子类化或其他方法有一些优势:

  • 没有额外的复杂性:代码中没有额外的类
  • 没有人可以“错误地”子类化并覆盖您的类:保留您的架构
  • 当你说一个方法受到保护时,你有点期望它会被覆盖。您正在告诉谁正在阅读您的代码。一个不应该被覆盖的受保护方法会让你的代码读者感到困惑,这违反了我的第一个编程原则:“代码必须写成其他人才能阅读。”
  • DUnit在他们自己的单位,不包括在任何地方
  • 你不要碰乱凌乱的RTTI。

我认为这是一个更清晰的解决方案,并且比选定的答案更好。

当我使用它时,我还配置测试项目以将构建对象放在主项目的不同目录中。这可以防止带有TEST指令的二进制文件与其他代码混合使用。

答案 2 :(得分:5)

我推荐杰拉德·梅萨罗斯的“XUnit Test Patterns”一书:

Test-Specific Subclass

  

问题:我们如何制作代码   我们需要访问时可测试   SUT的私有状态?

     

回答:添加公开的方法   测试所需的状态或行为   到SUT的子类。

     

...如果被测系统(SUT)没有   专门设计为可测试的,   我们可能会发现测试无法获得   访问必须的状态   在某个时间点初始化或验证   测试。

该文章还解释了何时使用它以及它带来的风险。

答案 3 :(得分:4)

将DUnit代码放入您的设备中。然后,您可以访问任何您喜欢的内容。

答案 4 :(得分:4)

总的来说,当我遇到这种情况时,我常常意识到我违反了单一责任原则。当然,我对你的具体案例一无所知,但也许,私人方法应该属于他们自己的班级。 TAuth将在其私人部分中引用这个新类。

答案 5 :(得分:2)

使用扩展RTTI (Delphi 2010及更新版本),通过RTTI调用私有方法是另一种选择。此解决方案也是How do I test a class that has private methods, fields or inner classes?

中评价最高的答案

答案 6 :(得分:2)

{$IFNDEF UNITEST}
private
{$ENDIF}

简单的解决方案,这几乎不是一个黑客。我经常需要测试私有方法,这种技术增加了尽可能少的复杂性。