我正在为一个庞大的 Delphi 代码库编写单元测试基础设施。例如,我想将对SysUtils.FileExists的调用链接到“MockSysUtils.FileExists”。创建具有相同接口的SysUtils单元将不受编译器欢迎。我的想法是在运行时挂接我的模拟函数。现在是否可能?还有其他建议吗?祝好,Peter。
VirtualProtect
) 去可写状态更简单的方法是链接到不同版本的SysUtils.pas。这将需要您重新编译依赖于SysUtils.pas的RTL和VCL中的所有单元,但它可能比上面描述的函数插桩方法容易得多。
最简单的方法是在语言级别上操作,其中您直接不依赖于SysUtils(因此可以在更高的级别上切换),或者修改uses
声明以有条件地引用不同的单元。
HookCode
函数,给它想要替换的函数地址和想要调用的函数地址。它会返回一个函数指针,你可以用它来调用原始函数并在取消挂钩后使用。实质上,它实现了 Barry 描述中的中间三个步骤。OverwriteProcedure
函数,那里也有如何使用它的示例。FileExists
函数(因为实际上确实是这样),但当它到达那里时,它将立即跳转到您的模拟版本。你也可以将仅包含你想要模拟的函数的单元添加到测试单元的 uses 子句中。Delphi 将始终使用列在最后的单元中的函数。不幸的是,这将需要你更改要测试的单元。
你的 Mock-Sysutils 单元:
unit MockSysutils;
interface
function FileExists(...) ...
...
end.
你想要测试的单元:
unit UnitTotest;
interface
uses
Sysutils,
MockSysUtils;
...
if FileExists(...) then
FileExists现在将调用MockSysutils版本而不是Sysutils版本。
谢谢,
如果有TSysUtils类的话,我可以通过继承我的MockSysUtils来使用它,但是现在并没有这样的情况,而且代码库非常庞大。虽然会逐步替换,但我想知道是否有快速解决方案。
第一种方法对于一个函数可能还可以,但在这种情况下不太可行。
我将采用第二种方法。
这可能有一点儿超前,但是这里还有另一个选择。
在构建单元测试和主代码库时,您可以使用grep查找所有要替换的函数,并指定要使用的单元。
而不是
fileexists(MyFilename);
你可以使用 grep fileexists 命令来查找并替换
MockTests.fileexists(MyFileName);