2011-09-09 117 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

感謝您的延伸解釋,我已經接受了類似的答案,我相信這是第一個發佈。 –

相關問題