هل هناك طريقة أنيقة لاختبار ما إذا كانت طريقة مثيل واحدة هي الاسم المستعار لآخر؟

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) ، لكنها لا تعتبر مكافئة بواسطة روبي 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) سوف ينتج 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