我正在使用 DUnit 对一个类进行单元测试。它有许多方法,一些公共方法和私有方法。

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

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

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

有帮助吗?

解决方案

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

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;

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

其他提示

这有点hacky,但我认为这是最简单、更清晰的方法。使用此条件编译指令:

  {$IfNDef TEST}
  private
  {$EndIf}

您的单元测试项目必须在中定义 TEST project → conditional defines. 。如果没有可见性规范,它们就会被发布。

谨防:如果私有可见性不是类声明中的第一个,它将获得先前的定义。一种更安全的方法,但更冗长且不太清晰,是:

  private
  {$IfDef TEST}
  public
  {$EndIf}

与子类化或其他方法相比,这有很多优点:

  • 没有额外的复杂性:您的代码中没有额外的类。
  • 没有人可以“错误地”子类化并覆盖你的类:你保留了你的建筑。
  • 当您说某个方法受到保护时,您有点期望它会被覆盖。你是在告诉谁正在阅读你的代码。不应重写的受保护方法会让您的代码读者感到困惑,从而违反了我的第一个编程原则: “代码必须编写成可供其他人阅读。”
  • DUnit 位于其自己的单元中,并非到处都包含。
  • 你不要碰乱七八糟的RTTI。

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

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

我建议使用“ XUnit测试模式”。 Gerard Meszaros的书:

特定于测试的子类

  

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

     

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

     

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

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

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

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

使用扩展RTTI (Delphi 2010及更新版本),通过RTTI调用私有方法是另一种选择。此解决方案也是如何测试具有私有方法,字段或内部类的类?

{$IFNDEF UNITEST}
private
{$ENDIF}

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top