Test doubles هي كائنات تحل محل التبعيات الحقيقية في الاختبارات — وتشمل mocks وstubs وspies وfakes وdummies. تعزل الكود المراد اختباره عن تبعياته (قواعد البيانات والـ APIs والخدمات)، مما يمكّن من اختبارات وحدة سريعة وموجهة ومضبوطة.
لماذا test doubles
To test a unit in ISOLATION, replace its real dependencies (DB, API, services) with
TEST DOUBLES (fake stand-ins):
→ isolate the unit (test ONLY it, not its dependencies)
→ FAST (no real DB/network); CONTROLLED (set up exact scenarios, including errors);
DETERMINISTIC (no external flakiness)
أنواع test doubles
STUB → provides canned RESPONSES to calls (returns preset data):
→ "when getUser is called, return this fake user" — controls inputs to the unit
MOCK → a stub that also VERIFIES interactions (was it called? how? with what?):
→ "verify save() was called once with these arguments" — checks behavior/interactions
SPY → wraps a real (or fake) object and RECORDS calls (verify how it was used)
FAKE → a working but simplified implementation (e.g. an in-memory database)
DUMMY → a placeholder passed but not actually used
// stub: control what a dependency returns
const userService = { getUser: jest.fn().mockReturnValue({ name: 'Ann' }) };
// mock verification: check an interaction happened
expect(emailService.send).toHaveBeenCalledWith('[email protected]');
Mock مقابل stub (التمايز الأساسي)
STUB → controls INPUTS (provides data the unit needs) — "state" verification
MOCK → verifies OUTPUTS/interactions (was the dependency called correctly?) — "behavior"
verification
→ Use stubs to provide data; mocks to verify the unit called a dependency correctly.
⚠️ Over-mocking → tests coupled to implementation (brittle); mock at the right boundaries.
أهمية الموضوع
فهم test doubles (mocks وstubs وغيرها) مهم لأنها ضرورية لكتابة اختبارات وحدة معزولة، لذلك فهي معرفة اختبار قيمة وتُطبق بشكل متكرر.
لاختبار وحدة بشكل معزول (الهدف من اختبار الوحدة)، يجب عليك استبدال تبعياتها الحقيقية (قواعد البيانات والـ APIs والخدمات) بـ test doubles — مما يمكّن من اختبارات سريعة (بدون إدخال/إخراج حقيقي)، مضبوطة (إعداد السيناريوهات المحددة بدقة بما فيها حالات الخطأ الصعبة التشغيل مع التبعيات الحقيقية)، وحتمية (بدون عدم استقرار خارجي).
فهم الأنواع وأغراضها ضروري: stubs (توفير استجابات محددة مسبقاً للتحكم فيما تعيده التبعيات — تغذية الوحدة ببيانات محددة)، mocks (stubs تتحقق أيضاً من التفاعلات — التحقق من استدعاء الوحدة للتبعية بشكل صحيح)، spies (تسجيل الاستدعاءات على الكائنات الحقيقية أو الوهمية)، fakes (تطبيقات مبسطة عاملة مثل قواعس بيانات في الذاكرة)، وdummies (عناصر نائبة).
فهم التمايز الأساسي بين mock و stub — stubs تتحكم في المدخلات (التحقق من الحالة: توفير البيانات) بينما mocks تتحقق من المخرجات/التفاعلات (التحقق من السلوك: التحقق من استدعاء الوحدة للتبعيات بشكل صحيح) — هي معرفة مفاهيمية مهمة غالباً ما يتم الخلط فيها، واستخدام كل منها بشكل مناسب مهم.
فهم فخ الإفراط في الـ mocking (الـ mocking المفرط يربط الاختبارات بتفاصيل التنفيذ، مما يجعلها هشة، لذا يجب عليك الـ mock في الحدود الصحيحة) يعكس حكماً ناضجاً في الاختبارات.
يتم استخدام test doubles بشكل مستمر في اختبارات الوحدة لعزل الكود المراد اختباره.
بما أن اختبار الوحدة المعزول يتطلب استبدال التبعيات الحقيقية بـ test doubles (من أجل السرعة والتحكم والحتمية)، وبما أن فهم الأنواع والتمايز بين mock و stub وفخ الإفراط في الـ mocking ضروري لكتابة اختبارات معزولة جيدة، فإن فهم test doubles هو معرفة اختبار قيمة وتُطبق بشكل متكرر — ضرورية لاختبار الوحدة، تُستخدم بشكل مستمر لعزل الكود، ومهمة لكتابة اختبارات موجهة ومضبوطة مع تجنب هشاشة الإفراط في الـ mocking، وهي مهارة أساسية للاختبار الفعال.
