2010-10-06 49 views
11

在單元測試中,我需要測試是否已正確定義由alias_method定義的別名方法。我可以簡單地對用於原始文件的別名使用相同的測試,但我想知道是否有更明確或有效的解決方案。例如,是否有辦法1)取消引用方法別名並返回其原始名稱,2)獲取並比較某種底層方法標識符或地址,或者3)獲取和比較方法定義?例如:有沒有一種優雅的方式來測試一個實例方法是否是另一個實例的別名?

class MyClass 
    def foo 
    # do something 
    end 

    alias_method :bar, :foo 
end 

describe MyClass do 
    it "method bar should be an alias for method foo" do 
    m = MyClass.new 
    # ??? identity(m.bar).should == identity(m.foo) ??? 
    end 
end 

建議?如果 被綁定到相同的對象和 包含相同的體

+0

可能重複[是否有可能確定在Ruby中走樣方法?(http://stackoverflow.com/questions/3676834/is-it-possible-to -identify-aliased-methods-in-ruby) – 2010-10-06 11:43:54

回答

18

根據用於Method文檔,

兩個方法的對象是相等的。

調用Object#method和比較Method對象,它返回將驗證方法是相同的:

m.method(:bar) == m.method(:foo) 
+0

我確定我記得這不起作用,但我只是試圖確認它,並且它在Ruby 1.8,1.9和MacRuby中一致地工作。但是我仍然沒有在RubySpec中看到它,所以它很可能不適用於不相關的實現。 – Chuck 2010-10-06 05:57:30

+2

另外,一般來說,僅具有相同物體但不相互複製的方法強調*不相等。證明:'類。新{def foo()結束; def bar()end; puts instance_method(:foo)== instance_method(:bar)}' – Chuck 2010-10-06 06:04:08

+0

@Chuck:謝謝你指出。我應該嘗試過。 – bk1e 2010-10-06 06:11:32

3

bk1e的方法工作的大部分時間,但我只是碰巧擊中的情況下它不「T工作:

class Stream 
    class << self 
    alias_method :open, :new 
    end 
end 

open = Stream.method(:open) 
new = Stream.method(:new) 
p open, new     # => #<Method: Stream.new>, #<Method: Class#new> 
p open.receiver, new.receiver # => Stream, Stream 
p open == new     # => false 

輸出Ruby 1.9中產生的,不知道這是否是一個錯誤或不因爲Ruby 1.8中最後李產生true東北。因此,如果您使用的是1.9,請注意如果您正在別名的繼承類方法(如Class#new),這兩個方法綁定到同一個對象(類對象Stream),但它們被認爲不等同於Ruby 1.9 。

我的解決方法很簡單 - 別名原來的方法再次測試兩個別名的平等:

class << Stream; alias_method :alias_test_open, :new; end 
open = Stream.method(:open) 
alias_test_open = Stream.method(:alias_test_open) 
p open, alias_test_open     # => #<Method: Stream.new>, #<Method: Stream.new> 
p open.receiver, alias_test_open.receiver # => Stream, Stream 
p open == alias_test_open     # => true 

希望這有助於。

UPDATE:

http://bugs.ruby-lang.org/issues/7613

所以Method#==應該在這種情況下返回false因爲super通話將調用不同的方法;這不是一個錯誤。

1

調用MyClass.instance_method(:foo)將導致UnboundMethod實例,其中有eql?方法。

所以答案是:

describe MyClass do 
    subject { described_class } 

    specify do 
    expect(subject.instance_method(:foo)).to be_eql(subject.instance_method(:bar)) 
    end 
end 
相關問題