在单元测试中,我需要测试由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
建议?
根据方法的文档,
两个方法对象相等,如果它们 绑定到同一个对象并且 包含相同的身体。
Object#method
并比较它返回的 Method
对象将验证这些方法是否等效:
m.method(:bar) == m.method(:foo)
bk1e的方法大部分时间都有效,但我只是碰巧遇到了不起作用的情况:
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
),但它们被认为不等效红宝石 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
希望这有帮助。
更新:
参见 http://bugs.ruby-lang.org/issues/7613
因此
Method#==
在这种情况下应该返回 false,因为 super
调用会调用不同的方法;这不是一个错误。
调用
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