2010-10-06 48 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 
相关问题