如何模拟内置运算符

时间:2017-06-28 16:07:01

标签: perl unit-testing

我需要模拟像unlinkrename这样的内置运算符作为测试套件的一部分。我无法使用Test::MockObject

来解决此问题
>> my $mock = Test::MockObject->new();
>> $mock->mock('unlink', sub { print "Mocked!\n"; });
>> unlink "foo";
0

是否可以模拟这样的内置函数?

1 个答案:

答案 0 :(得分:5)

请参阅overriding core functions

  

要使用您自己的版本覆盖Perl内置例程,您需要在编译时导入它。使用subs编译指示可以方便地实现这一点。这只会影响您导入所述子程序的包:

   use subs 'chdir';
    sub chdir { ... }
    chdir $somewhere;
     

要覆盖全局内置(即在所有名称空间中),您需要在编译时将函数导入CORE::GLOBAL伪名称空间:

    BEGIN {
        *CORE::GLOBAL::hex = sub {
            # ... your code here
        };
    }
     

只要在没有合格包的情况下调用内置函数,就会调用新例程:

   print hex("0x50"),"\n";            # prints 1
     

在这两种情况下,如果您想要访问原始的未更改的例程,请使用CORE::前缀:

   print CORE::hex("0x50"),"\n";      # prints 80

另见the relevant section in perldoc perlsub

  

当您覆盖内置函数时,您的替换应该与内置本机语法保持一致(如果可能)。您可以通过使用合适的原型来实现此目的。要获得可覆盖内置的原型,请使用带有参数" CORE::builtin_name"的原型函数。 (见prototype)。

     

但请注意,某些内置函数的语法不能由原型(例如system或chomp)表示。如果你覆盖它们,你将无法完全模仿它们的原始语法。

     

内置插件dorequireglob can也会被覆盖,但由于特殊魔法,原始语法会被保留,您无需定义替换原型。 (但你不能覆盖do BLOCK语法。

     

require还有一些额外的黑暗魔法:如果您将require替换为require Foo::Bar,它实际上会在"Foo/Bar.pm"中收到@_参数。请参阅require

     

而且,正如您在上一个示例中所注意到的,如果覆盖glob,则<*> glob运算符也会被覆盖。

     

以类似的方式,覆盖readline函数也会覆盖等效的I / O运算符<FILEHANDLE>。此外,覆盖readpipe也会覆盖运算符``和qx//

     

最后,某些内置插件(例如existsgrep)无法覆盖。