あるインスタンスメソッドが別のインスタンスのエイリアスであるかどうかをテストするエレガントな方法はありますか?

StackOverflow https://stackoverflow.com/questions/3869668

  •  28-09-2019
  •  | 
  •  

質問

ユニットテストでは、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

提案?

役に立ちましたか?

解決

のドキュメントによると 方法,

2つのメソッドオブジェクトは、同じオブジェクトにバインドされ、同じ本体が含まれている場合、等しくなります。

電話 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を使用している場合は、継承されたクラスメソッド(クラス#newなど)をエイリアシングしている場合は注意してください。これらの2つの方法は同じオブジェクト(クラスオブジェクトにバインドされています。 Stream)、しかし、それらはRuby 1.9と同等ではないと見なされます。

私の回避策はシンプルです - 元の方法をもう一度エイリアスし、2つのエイリアスの平等をテストします。

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#== この場合、a 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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top