【发布时间】:2017-03-07 10:28:59
【问题描述】:
考虑一个模块,它导出一个连接到 Internet 并返回结果的子例程:
unit module A;
sub download is export {
"result from internet" # Not the actual implementation, obviously.
}
还有另一个导入和调用该子程序的模块:
use A; # imports &download into this lexical scope
unit module B;
sub do-something is export {
download().uc ~ "!!" # Does something which involves calling &download
}
现在我想为模块 B 编写单元测试。
但我不希望测试实际连接到 Internet;我希望他们使用由我的测试脚本控制的子例程 download 的模拟版本:
use Test;
plan 2;
use B;
my $mock-result;
my &mock-download = -> { $mock-result }
# ...Here goes magic code that installs &mock-download
# as &download in B's lexical scope...
$mock-result = "fake result";
is do-something(), "FAKE RESULT!!", "do-something works - 1";
$mock-result = "foobar";
is do-something(), "FOOBAR!!", "do-something works - 2";
问题是缺少用于覆盖子download...的魔术代码...
在 Perl 5 中,我认为这可以很容易地使用 glob 分配来实现,或者在 Sub::Override 或 Test::MockModule 的帮助下更好。
但是在 Perl 6 中,模块 B 的词法范围在它完成编译后关闭,因此在运行测试脚本时无法再修改(如果我错了,请纠正我)。所以这种方法似乎是不可能的。
那么,如何在 Perl 6 中解决这个任务呢?
IE。如何为B::do-something 编写单元测试,而不让它调用真正的A::download?
【问题讨论】:
标签: unit-testing mocking raku