有没有办法在Perl中模拟内置的require函数?
我正在开发一个应用程序,它必须一块一块地替换现有的杂乱无章的代码。为了实现这一点,我有一个dispatcher,在URI匹配时运行所需的HTTP资源,否则使用遗留HTTP资源类 因此,这个遗留HTTP资源必须有没有办法在Perl中模拟内置的require函数?,perl,unit-testing,mocking,Perl,Unit Testing,Mocking,我正在开发一个应用程序,它必须一块一块地替换现有的杂乱无章的代码。为了实现这一点,我有一个dispatcher,在URI匹配时运行所需的HTTP资源,否则使用遗留HTTP资源类 因此,这个遗留HTTP资源必须需要旧系统的入口点文件,我正试图找出如何测试这个过程。我现在看到的是,我想用一个模拟子例程替换原来的require函数,并检查是否已使用适当的文件名调用它 这可能吗?如果不可能,可能有更好的方法吗?要在单个包中覆盖require: use subs 'require'; # imports
需要旧系统的入口点文件,我正试图找出如何测试这个过程。我现在看到的是,我想用一个模拟子例程替换原来的require
函数,并检查是否已使用适当的文件名调用它
这可能吗?如果不可能,可能有更好的方法吗?要在单个包中覆盖require
:
use subs 'require'; # imports `require` so it can be overridden
sub require {print "mock require: @_\n"}
要全局覆盖要求
:
BEGIN {
*CORE::GLOBAL::require = sub {print "mock require: @_\n"}
}
然后:
require xyz; # mock require: xyz.pm
require Some::Module; # mock require: Some/Module.pm
全局覆盖require
的更好方法可能是在@INC
中安装一个钩子。这个鲜为人知的功能将在本章末尾介绍
下面是一个简单的示例,用于拦截对名称以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;
请注意,这也会模拟use
,因为它基于require
钩子可以作为代码引用添加到@INC
路径中。然后这些将全局应用于use
和require
语句
引用perldoc的话
还可以通过将Perl代码直接放入@INC数组,将钩子插入导入工具
钩子有三种形式:子例程引用、数组引用和对象。
子程序引用是最简单的情况。当包含系统遍历@INC并遇到子例程时,将使用两个参数调用该子例程,第一个参数是对自身的引用,第二个参数是要包含的文件的名称(例如,“Foo/Bar.pm”)。子例程应返回nothing(无),或按以下顺序返回最多三个值的列表:
一,。从中读取文件的文件句柄
二,。对子程序的引用。如果没有filehandle(上一项),则该子例程将在每次调用中生成一行源代码,将该行写入$并返回1,最后在文件末尾返回0。如果有filehandle,则将调用该子例程作为简单的源筛选器,行为在$\中读取。同样,每个有效行返回1,所有行返回后返回0
3.子程序的可选状态。该状态作为$\uU1]传入。对子例程本身的引用作为$\u0[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及更高版本是有效的。这难道不模拟只需要该模块的函数吗?我需要它被嘲笑为所有其他模块以及。感谢扩展的解释,我已经接受了类似的答案,我相信这是第一次张贴。