【问题标题】:How to mock an imported subroutine when unit-testing a module单元测试模块时如何模拟导入的子例程
【发布时间】: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::OverrideTest::MockModule 的帮助下更好。

但是在 Perl 6 中,模块 B 的词法范围在它完成编译后关闭,因此在运行测试脚本时无法再修改(如果我错了,请纠正我)。所以这种方法似乎是不可能的。

那么,如何在 Perl 6 中解决这个任务呢?
IE。如何为B::do-something 编写单元测试,而不让它调用真正的A::download

【问题讨论】:

    标签: unit-testing mocking raku


    【解决方案1】:

    最简单的方法可能是使用wrap,在https://docs.perl6.org/language/functions#Routines 中有描述,但前提是use soft; pragma 可以防止内联。您需要在模块 A 中 use soft;

    unit module A;
    use soft;
    
    sub download is export {
        "result from internet";
    }
    

    模块 B:

    unit module B;
    use A;
    
    sub do-something is export {
        download.uc ~ "!!";
    }
    

    还有测试脚本:

    use Test;
    use A;
    use B;
    
    &download.wrap({
        "mock result";
    });
    
    is do-something, "MOCK RESULT!!", "mock a 'use'd sub";
    # ok 1 - mock a 'use'd sub
    

    【讨论】:

    • 我对这个答案不满意。需要使用use soft; 定义的(通常是外部的)模块来模拟导入的子程序似乎是不合理的。真的没有办法修改A或B的符号表吗?如果没有,是否至少有办法以某种方式修改模块 B 以使其更具可测试性?
    • 回溯到新的相关问题stackoverflow.com/questions/63042080/… :: 另外,使用 soft 是一个编译指示,而不是一个模块 - 所以普遍可用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2020-06-04
    • 2015-12-10
    相关资源
    最近更新 更多