我有一门课,我正在用 DUnit 对它进行单元测试。它有许多方法一些公共方法和私有方法。
type
TAuth = class(TDataModule)
private
procedure PrivateMethod;
public
procedure PublicMethod;
end;
为了为此类编写单元测试,我必须公开所有方法。
是否有不同的方法来声明私有方法,以便我仍然可以测试它们但它们不是公共的?
我有一门课,我正在用 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}
您的单元测试项目必须在project → conditional defines
. 如果没有可见性规范,它们就会被发布。
注意:如果私有可见性不是类声明中的第一个可见性,它将获得先前的定义。一种更安全但更冗长且不太清晰的方法是:
private
{$IfDef TEST}
public
{$EndIf}
与子类化或其他方法相比,这有很多优点:
我认为这是一个更清晰的解决方案,并且比选定的答案更好。
当我使用它时,我还将测试项目配置为将构建对象放在主项目的不同目录中。这可以防止带有 TEST 指令的二进制文件与其他代码混合。
我推荐 Gerard Meszaros 的“ XUnit 测试模式”一书:
问题:当我们需要访问 SUT 的私有状态时,如何使代码可测试?
答案:添加将测试所需的状态或行为暴露给 SUT 的子类的方法。
...如果被测系统 (SUT) 不是专门为可测试而设计的,我们可能会发现测试无法访问必须在测试中的某个时间点进行初始化或验证的状态。
文章还解释了何时使用它以及它会带来哪些风险。
将 DUnit 代码放入您的单元中。然后,您可以访问任何您喜欢的内容。
一般来说,当我遇到这种情况时,我经常意识到我违反了单一责任原则。当然,我对您的具体情况一无所知,但也许,私有方法应该在他们自己的类中。TAuth 将在其私有部分中引用这个新类。
使用扩展 RTTI(Delphi 2010 和更新版本),通过 RTTI 调用私有方法是另一种选择。此解决方案也是如何测试具有私有方法、字段或内部类的类中最受好评的答案?
{$IFNDEF UNITEST}
private
{$ENDIF}
简单的解决方案,这几乎不是一个黑客。我经常需要测试私有方法,而这种技术会尽可能减少复杂性。