لماذا الاختبارات بدون كائنات وهمية مثل الطهي بدون ملح
\n\nتخيل أنك تكتب تطبيقًا يرسل إشعارات البريد الإلكتروني، ويعمل مع قاعدة البيانات، ويتصل بـ API خارجي. كيف ستختبر هذا بدون كائنات وهمية وبيانات اختبارية في PHP؟ ستضطر كل مرة لإرسال رسائل حقيقية، وإنشاء سجلات اختبارية في قاعدة البيانات، وانتظار رد من الخدمة الخارجية. هذا بطيء، غير موثوق، وببساطة غير ذكي.
\n\nهنا تأتي بدائل الاختبار لإنقاذك — بدائل للكائنات الحقيقية. في نظام PHP البيئي، نستخدم مزيجًا من: كائنات وهمية (mock) للتحقق من التفاعلات و بيانات اختبارية (fixtures) لإعداد البيانات. دعنا نفهم كيف يعمل هذا عمليًا.
\n\nMock vs Stub vs Fake: لا تخلط بينهم
\n\nقبل الغوص في الكود، دعنا نضع النقاط على الحروف. في عالم اختبارات الوحدة في PHP، هناك ثلاثة أنواع رئيسية من البدائل:
\n\n- \n
- دعامة (Stub) — يعيد بيانات محددة مسبقًا. تتحقق من أن كودك يعالج هذه البيانات بشكل صحيح. \n
- محاكاة (Mock) — لا يعيد البيانات فقط، بل يتحقق أيضًا من كيفية استدعاء النظام للطرق: كم مرة، بأي وسائط، وبأي ترتيب. \n
- مزيف (Fake) — تنفيذ عملي مبسط (مثل قاعدة بيانات في الذاكرة). \n
في PHPUnit، وهو المعيار الفعلي لـ اختبارات PHP، غالبًا ما يتم الخلط بين هذه المفاهيم. لكننا سنكون دقيقين: الكائنات الوهمية في PHP هي تلك التي تحدد فيها التوقعات (expectations).
\n\nكتابة أول كائن وهمي باستخدام PHPUnit
\n\nلنفترض أن لدينا كلاس Mailer يرسل رسائل البريد الإلكتروني. نريد التحقق من أن خدمة التسجيل تستدعي الطريقة send() مرة واحدة بالضبط مع البيانات الصحيحة.
<?php\nuse PHPUnit\\Framework\\TestCase;\n\nclass UserRegistrationTest extends TestCase\n{\n public function testSendWelcomeEmailOnRegistration(): void\n {\n // إنشاء كائن وهمي لـ Mailer\n $mailer = $this->createMock(Mailer::class);\n \n // إعداد التوقع: سيتم استدعاء send مرة واحدة\n $mailer->expects($this->once())\n ->method('send')\n ->with(\n $this->equalTo('user@example.com'),\n $this->stringContains('Welcome')\n );\n \n $service = new UserRegistrationService($mailer);\n $service->register('user@example.com', 'password123');\n }\n}\n\n\nلاحظ: نحن لا نتحقق من أن الرسالة أُرسلت فعليًا. نحن نتحقق من أن كودنا حاول إرسالها — وهذا هو جوهر الكائنات الوهمية في اختبارات PHP. إذا لم يتم استدعاء الطريقة send() (أو تم استدعاؤها مرتين)، سيفشل الاختبار.
طريقة expects وإمكانياتها
\n\nيوفر PHPUnit واجهة برمجة تطبيقات غنية لإعداد التوقعات:
\n\n- \n
$this->once()— استدعاء واحد بالضبط \n $this->exactly(3)— ثلاثة استدعاءات بالضبط \n $this->atLeastOnce()— استدعاء واحد على الأقل \n $this->never()— لا يجب استدعاء الطريقة أبدًا \n
بالنسبة للوسائط، استخدم المطابقات (constraints):
\n\n$mailer->expects($this->once())\n ->method('send')\n ->with(\n $this->callback(function($email) {\n return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;\n }),\n $this->anything() // لا نهتم بالوسيط الثاني\n );\n\n\nالبيانات الاختبارية في PHP: إعداد البيانات قبل أن تحتاجها
\n\nالبيانات الاختبارية (Fixtures) هي حالة بيانات محددة مسبقًا يكون فيها النظام قبل تنفيذ الاختبار. في PHPUnit، نستخدم الطريقتين setUp() و