如何模拟内置运算符

ewo*_*wok 4 perl unit-testing

我需要模拟内置运算符,unlink并将其rename作为测试套件的一部分.我无法使用它Test::MockObject

>> my $mock = Test::MockObject->new();
>> $mock->mock('unlink', sub { print "Mocked!\n"; });
>> unlink "foo";
0
Run Code Online (Sandbox Code Playgroud)

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

Sin*_*nür 5

请参阅覆盖核心功能:

要使用您自己的版本覆盖Perl内置例程,您需要在编译时导入它.这可以通过subs pragma 方便地实现.这将仅影响您导入所述子例程的包:

   use subs 'chdir';
    sub chdir { ... }
    chdir $somewhere;
Run Code Online (Sandbox Code Playgroud)

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

    BEGIN {
        *CORE::GLOBAL::hex = sub {
            # ... your code here
        };
    }
Run Code Online (Sandbox Code Playgroud)

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

   print hex("0x50"),"\n";            # prints 1
Run Code Online (Sandbox Code Playgroud)

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

   print CORE::hex("0x50"),"\n";      # prints 80
Run Code Online (Sandbox Code Playgroud)

另见以下相关章节perldoc perlsub:

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

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

内置插件do,require并且glob can也被覆盖,但由于特殊的魔力,原来的语法保留,你不必定义为原型的替代品.(但你不能覆盖do BLOCK语法).

require有特殊附加黑暗魔法:如果你调用你require更换的require Foo::Bar,它实际上将得到的说法"Foo/Bar.pm"@_.见require.

并且,正如您在上一个示例中已经注意到的那样,如果覆盖glob,则<*>也会覆盖glob运算符.

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

最后,一些内置插件(例如exists或者grep)不能被覆盖.

  • Re"*Perfect!以后可以取消函数吗?*",最好不要解开.相反,使用标志.`sub {if($ mock_active){...} else {CORE :: chdir(...); }` (3认同)
  • *"以后可以取消函数吗?"*我不明白为什么你想要在测试程序中,但你必须写`*chdir = \&CORE :: chdir`. (2认同)