كيف يعمل "انعكاس ثابت" في جافا؟ (على سبيل المثال في Mockito أو Easymock)
-
06-07-2019 - |
سؤال
أنا رجل .NET - وأنا رمز بشكل رئيسي في C#.
منذ C# 3.0 ، يمكننا الاستفادة من تعبيرات Lambda وأشجار التعبير للاستخدام انعكاس ثابت. على سبيل المثال ، من الممكن التنفيذ GetMethodName
في المقتطف التالي لإرجاع اسم الطريقة التي تم تمريرها في المعلمة:
string methodName = GetMethodName( o => o.DoSomething());
Console.WriteLine(methodName); // displays "DoSomething"
الآن ، عندما أنظر إلى عينات Mockito (أو عينات Easymock) في عالم Java ، أرى:
LinkedList mockedList = mock(LinkedList.class);
when(mockedList.get(0)).thenReturn("first");
كيف يعمل؟
كيف يمكن لل when
طريقة العمل؟ كيف يفسر mockedList.get(0)
كما مكالمة إلى طريقة GET مع تمرير 0 كمعلمة وليس كقيمة؟
المحلول
لا تعمل المكتبات الساخرة عادة مع أشجار التعبير. يقومون بإنشاء نوع ينفذ الواجهة المناسبة ويستجيب لمكالمات الطريقة إما عن طريق تسجيلها أو التحقق من صحةها وإعادة الاستجابات المبرمجة مسبقًا. عادة ما يتم ذلك باستخدام وكيل (على سبيل المثال RealProxy في الشباك، الوكيل في جافا) أو مع توليد الكود الديناميكي.
في حالة Easymock ، فإنه يستخدم Proxy
(للواجهات ، على أي حال) ، كما ترون في الكود المصدري: انظر إلى org.easymock.internal.JavaProxyFactory
.
نصائح أخرى
عادة ما تعمل مكتبات Java Mock مثل هذا:
عند إنشاء وهمية ، يتم إنشاء وكيل فعلي (سواء كان ذلك من واجهة أو فئة فرعية) ، يكون المثيل في "وضع التسجيل". هذا يعني أنه يتم تسجيل أي مكالمة لاحقة (اسم الطريقة ، المعلمات ، الإرجاع المتوقع). لاحظ أن الوكيل في وضع التسجيل لا يفعل شيئًا سوى تسجيل المكالمات. لا يوجد انعكاس لكل سى. لا يوجد اكتشاف البيانات الوصفية ، وما إلى ذلك. بالطبع تقوم هذه المكتبات ببعض الحيل (مثل تخزين الدعوات في متغير محلي مؤشر الترابط للتعامل مع الأساليب التي يعيد باطلة) ولكن الفكرة تظل كما هي.
بعد ذلك ، عند بدء تشغيل "وضع إعادة التشغيل" ، يقوم مثيل Mock ببساطة بالتحقق من التوقعات من قائمة الدعوات (Method+Parameters وقيم الإرجاع).
لم أعمل مطلقًا مع Mockito أو Easymock ، لكنني لا أعتقد أن المكالمة تفعل ما تعتقد أنه. لا يفسر mockedList.get(0)
بأي طريقة خاصة. طريقة get
يتم تنفيذها على mockedList
الكائن بشكل طبيعي ، و نتيجة من ذلك يتم تسليمه إلى when
.
mockedList.get(0)
هو بناء الجملة لمكالمة الطريقة ، ويفعل ذلك بالضبط. ما تفعله هذه الطريقة غير واضح تمامًا. mockedList
سيكون نوع وقت التشغيل فئة فرعية LinkedList
عاد من قبل mock
الطريقة ، التي يمكن تنفيذها كيف يرى إطار السخرية مناسبة.