Domanda

In un test di unità ho bisogno di testare se i metodi di alias definiti da alias_method sono stati adeguatamente definiti. Potrei semplicemente utilizzare gli stessi test sugli alias utilizzati per le loro originali, ma mi chiedo se c'è una soluzione più definitiva o efficiente. Per esempio, c'è un modo per 1) dereference un metodo alias e restituisce il suo nome originale, 2) get e confrontare un qualche tipo di sottostante metodo di identificazione o l'indirizzo, o 3) get e confrontare definizioni dei metodi? Ad esempio:

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

Suggerimenti?

È stato utile?

Soluzione

Secondo la documentazione per Metodo ,

  

Due oggetti metodi sono uguali se tale   sono legati allo stesso oggetto e   contengono lo stesso corpo.

Object#method e confrontando gli oggetti che Method restituisce verificherà che i metodi sono equivalenti:

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

Altri suggerimenti

Il metodo di bk1e funziona la maggior parte del tempo, ma mi è capitato di colpire il caso in cui non funziona:

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

L'uscita è prodotta in Ruby 1.9, non so se si tratta di un bug o no dal momento che Ruby 1.8 produce true per l'ultima riga. Quindi, se si utilizza 1.9, fare attenzione se si sta aliasing un metodo di classe ereditata (come Class # nuovo), Questi due metodi sono legati allo stesso oggetto (l'Stream oggetto di classe), ma sono considerati non equivalenti da Ruby 1.9 .

La mia soluzione è semplice - alias il metodo originale di nuovo e verificare l'uguaglianza delle due alias:

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

Spero che questo aiuti.

UPDATE:

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

Quindi Method#== dovrebbe restituire false in questo caso, poiché una chiamata super sarebbe invocare metodi diversi; non è un bug.

La chiamata MyClass.instance_method(:foo) si tradurrà UnboundMethod esempio, che ha eql? metodo.

Quindi la risposta è:

describe MyClass do
  subject { described_class }

  specify do
    expect(subject.instance_method(:foo)).to be_eql(subject.instance_method(:bar))
  end
end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top