2011-09-09 75 views
4

我正在开发一个应用程序,它必须逐块替换现有的意大利面条代码。为了达到这个目的,我有一个调度器,它在URI匹配时运行所需的HTTP资源,否则使用传统的HTTP资源类。有没有办法在Perl中模拟内置的require函数?

因此,这个传统的HTTP资源必须require旧系统的入口点文件,我想弄清楚如何测试这个过程。我现在看到的方式是我想用模拟子程序替换原始的require函数,并检查它是否已用适当的文件名称进行调用。

这是可能的,如果没有,也许有更好的方法来做到这一点?

回答

10

一种更好的方式来覆盖require全局可在中安装挂钩3210。这个鲜为人知的功能在the require documentation的末尾进行了描述。

这里有一个简单的例子,用于拦截模块名称以HTTP的任何请求:

BEGIN { 
    unshift @INC, sub { 
    my ($self, $file) = @_; 
    return unless $file =~ /^HTTP/; 
    print "Creating mock $file\n"; 
    my @code = "1"; # Fake module must return true 
    return sub { $_ = shift @code; defined $_ }; 
    } 
} 

require HTTP::Foo; 
use HTTPBar; 

注意,因为它是基于require,这也嘲笑use

13

要在单个封装覆盖require

use subs 'require'; # imports `require` so it can be overridden 

sub require {print "mock require: @_\n"} 

要覆盖require全局:

BEGIN { 
    *CORE::GLOBAL::require = sub {print "mock require: @_\n"} 
} 

然后:

require xyz;   # mock require: xyz.pm 

require Some::Module; # mock require: Some/Module.pm 
+0

难道这不会模拟只有该模块的“需要”功能吗?我也需要它为所有其他模块嘲笑。 –

+0

是的,请参阅全局版本的更新。 –

+0

谢谢,它的工作原理,但我决定使用钩子。 –

2

你需要注意的其他一些东西。这要么补充或取代覆盖require的需要。

您是否知道您可以在您的@INC路径中添加钩子作为代码参考?这些将在全球范围内适用于userequire报表。

引用的perldoc require

您也可以通过将Perl代码直接到@INC数组插入挂钩插入导入工具。

有三种形式的钩子:子程序引用,数组引用和祝福对象。

子程序引用是最简单的情况。当包含系统遍历@INC并遇到一个子例程时,这个子例程会被调用两个参数,第一个是对自身的引用,第二个是要包含的文件名(例如“Foo/Bar.pm”) 。该子程序应该按照下面的顺序返回任何内容或者最多三个值的列表:

1.一个文件句柄,从中读取文件。

2.对子程序的引用。如果没有文件句柄(前一个项目),那么这个子程序应该为每个调用产生一行源代码,将行写入$ _并返回1,最后在文件结尾返回0。如果存在文件句柄,则将调用该子例程以充当简单源过滤器,其中该行在$ _中读取。再次,每个有效行返回1,所有行返回后返回0。

3.子程序的可选状态。状态以$ _ [1]的形式传入。在子程序自身的引用传入为$ _ [0]

下面是一个例子:

#!/usr/bin/perl 

sub my_inc_hook { 
    my ($sub_ref, $file) = @_; 

    unless ($file =~ m{^HTTP/}) { 
     warn "passing through: $file\n"; 
     return; 
    } 

    warn "grokking: $file\n"; 
    return (\*DATA); 
} 

BEGIN { 
    unshift(@INC, \&my_inc_hook); 
} 

use strict; 
require warnings; 
require HTTP::Bazinga; 

HTTP::Bazinga::it_works(); 

__DATA__ 
package HTTP::Bazinga; 

sub it_works {warn "bazinga!\n"}; 

1; 

产地:

$ perl inc.pl 
passing through: strict.pm 
passing through: warnings.pm 
grokking: HTTP/Bazinga.pm 
bazinga! 

我相信这个工程的Perl 5.10.0以上。

+1

它也适用于5.8。 – cjm

+0

感谢您的延伸解释,我已经接受了类似的答案,我相信这是第一个发布。 –

相关问题