我有一个班级,我正在与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指令的二进制文件与其他代码混合.
我推荐Gerard Meszaros 的" XUnit Test Patterns "一书:
特定于测试的子类
问题:当我们需要访问SUT的私有状态时,我们如何才能使代码可测试?
答案:添加将测试所需的状态或行为暴露给SUT的子类的方法.
...如果被测系统(SUT)并非专门设计为可测试的,我们可能会发现测试无法访问状态,表明它必须在测试的某个时刻进行初始化或验证.
该文章还解释了何时使用它以及它带来的风险.