Y at-il une façon élégante de tester si une méthode d'instance est un alias pour un autre?
-
28-09-2019 - |
Question
Dans un test unitaire je dois tester si ont été correctement défini des méthodes d'alias définis par alias_method. Je pourrais simplement utiliser les mêmes tests sur les alias utilisés pour leurs originaux, mais je me demande s'il y a une solution plus définitive ou efficace. Par exemple, est-il un moyen de 1) déréférencer un alias de méthode et retourne son nom d'origine, 2) get et comparer une sorte de sous-jacents identifiant ou adresse méthode ou 3) get et comparer les définitions de méthode? Par exemple:
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
Suggestions?
La solution
Selon la documentation Méthode ,
Deux objets de méthode sont égales si ce sont liés au même objet et contenir le même corps.
Object#method
et comparer les objets qui Method
il retourne vérifiera que les méthodes sont équivalentes:
m.method(:bar) == m.method(:foo)
Autres conseils
La méthode de bk1e fonctionne la plupart du temps, mais je vient de se passer de frapper le cas où il ne fonctionne pas:
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
La sortie est produite en Ruby 1.9, pas sûr que ce soit un bug ou non, puisque Ruby 1.8 produit true
pour la dernière ligne. Donc, si vous utilisez 1.9, soyez prudent si vous aliasing une méthode de classe héritée (comme classe # nouveau), ces deux méthodes sont liés au même objet (l'objet de classe Stream
), mais ils ne sont pas considérés comme équivalent par Ruby 1.9 .
Ma solution est simple - alias la méthode originale de nouveau et tester l'égalité des deux 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
Hope this helps.
Mise à jour:
Voir http://bugs.ruby-lang.org/issues/7613
Alors Method#==
devrait revenir faux dans ce cas depuis un appel super
invoquerait différentes méthodes; il est pas un bug.
L'appel MyClass.instance_method(:foo)
entraînera UnboundMethod par exemple, qui a eql?
méthode.
La réponse est:
describe MyClass do
subject { described_class }
specify do
expect(subject.instance_method(:foo)).to be_eql(subject.instance_method(:bar))
end
end