2014-02-13 86 views

回答

4

您的模擬潛艇模塊:

no warnings; 
local *Foo::bar = sub { 
    # do stuff 
}; 
use warnings; 

您通常要設置一個變量稍後在你的模擬測試中進行檢查。

(即使我建議使用測試:: MockModule,但明確規定不使用它)

2

這很難說,你可能有什麼樣的條件來解決,因爲你不給太多細節。因此,這是對嘲笑子程序涉及的內容的總體概述。

Perl在符號表中存儲包子程序,我們可以通過"globs"來訪問。以子程序do_the_thingSome::Package,您分配給符號的最後一個子程序*Some::Package::do_the_thing將取代該子的正常功能。我們也可以檢索它,以便我們可以打電話。

my $do_the_original_thing = *Some::Package::do_the_thing{CODE}; 

注意,要訪問它,我們要告訴它進入全局的CODE插槽。爲了取代sub,我們不這樣做。 Perl知道將代碼參考分配給glob的CODE槽。

*Some::Package::do_the_thing = sub { 
    if ($_[0] eq '-reallyreallydoit' and $_[1]) { 
     shift; shift; 
     goto &$do_the_original_thing; # this does not return here 
    } 
    # do the mock thing 
    ... 
}; 

注:顯示的方式展示了一個最小的方式來調用一個過程所以它的行爲就像的過程中,您會嘲諷。如果你不喜歡goto,那麼這個做同樣的事情:

 #goto &$do_the_original_thing; # this does not return here 
     return &$do_the_original_thing; # this returns here...to return 

但是,如果你想測試返回了什麼,或存儲它來建立未來的測試,你可以簡單地做這樣的:

my $future_test_value ; 
*Some::Package::do_the_thing = sub { 
    if ($_[0] eq '-reallyreallydoit' and $_[1]) { 
     shift; shift; 
     my @res; 
     if (wantarray) { 
      @res = &$do_the_original_thing; 
     } 
     elsif (!(wantarray // 1)) { 
      $res[0] = &$do_the_original_thing; 
     } 
     $future_test_value = $res[0]; 
     return wantarray ? @res : $res[0]; 
    } 
+0

這其實很好。但有沒有一種方法使用這個沒有goto語句? – ganezdragon

+1

@ ganezdragon查看編輯。 – Axeman