Есть ли элегантный способ проверить, если один метод экземпляра является псевдоним для другого?

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

Предложения?

Это было полезно?

Решение

Согласно документации для Метод,

Два объекта метода равны, если они связаны с тем же объектом и содержат одно и то же тело.

Призыв 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, будьте осторожны, если вы псевдоним методом унаследованного класса (например, класс # новый), эти два метода связаны с тем же объектом (объект класса 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

Надеюсь это поможет.

ОБНОВИТЬ:

Видеть http://bugs.ruby-lang.org/issues/7613.

Так Method#== должен вернуть ложь в этом случае с super вызов будет вызывать разные методы; Это не ошибка.

Призыв MyClass.instance_method(:foo) приведет к Несообщение экземпляр, который имеет 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