هل هناك طريقة أنيقة لاختبار ما إذا كانت طريقة مثيل واحدة هي الاسم المستعار لآخر؟
-
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