ما هو Mockito ولماذا هو مطلوب؟
\n\nMockito هي مكتبة قوية لجافا، مصممة لإنشاء كائنات mock (كائنات وهمية) في الاختبارات الوحدوية. تتيح لك عزل الكود المختبر عن تبعياته، مثل قواعد البيانات، واجهات API الخارجية، أنظمة الملفات أو الخدمات الأخرى. بدلاً من الكائنات الحقيقية، التي قد تكون بطيئة أو غير مستقرة أو تتطلب إعدادًا معقدًا، تقوم بإنشاء محاكاة لها بسلوك محدد مسبقًا.
\n\nالهدف الرئيسي لـ Mockito هو جعل الاختبارات الوحدوية سريعة، قابلة للتنبؤ، ومستقلة عن البيئة الخارجية. تُستخدم المكتبة على نطاق واسع في نظام جافا البيئي (Spring، Java EE، Android) وهي المعيار الفعلي للمحاكاة (mocking).
\n\nالإمكانيات الرئيسية:
\n- \n
- إنشاء كائنات mock — محاكاة أي فئة أو واجهة. \n
- تحديد السلوك — ضبط القيم المُعادة، إلقاء الاستثناءات. \n
- التحقق من الاستدعاءات — التأكد من استدعاء الطرق بمعاملات محددة وعدد المرات المطلوب. \n
- Spy (المحاكاة الجزئية) — إمكانية استخدام كائن حقيقي مع إعادة تعريف طرق معينة. \n
- التقاط المعاملات (ArgumentCaptor) — استخراج المعاملات المُمررة إلى طريقة mock للتحقق منها لاحقًا. \n
تثبيت Mockito
\n\nنظرًا لأن Mockito هي مكتبة جافا، فهي لا تُثبت عبر pip أو npm. للربط بالمشروع، تُستخدم أنظمة البناء Maven أو Gradle.
\n\nMaven (pom.xml)
\n<dependency>\n <groupId>org.mockito</groupId>\n <artifactId>mockito-core</artifactId>\n <version>5.12.0</version>\n <scope>test</scope>\n</dependency>\n\n<!-- للاستخدام مع JUnit 5 -->\n<dependency>\n <groupId>org.mockito</groupId>\n <artifactId>mockito-junit-jupiter</artifactId>\n <version>5.12.0</version>\n <scope>test</scope>\n</dependency>\n\nGradle (build.gradle)
\ntestImplementation 'org.mockito:mockito-core:5.12.0'\ntestImplementation 'org.mockito:mockito-junit-jupiter:5.12.0'\n\nيُوصى باستخدام أحدث إصدار ثابت، المتاح وقت كتابة الاختبارات.
\n\nبداية سريعة: مثال كود
\n\nلنأخذ مثالًا بسيطًا. لنفترض أن لدينا كلاس UserService يعتمد على UserRepository. نريد اختبار UserService دون تشغيل قاعدة البيانات.
// كلاس المستودع (التبعية)\npublic interface UserRepository {\n User findById(Long id);\n void save(User user);\n}\n\n// كلاس الخدمة (القابل للاختبار)\npublic class UserService {\n private final UserRepository userRepository;\n\n public UserService(UserRepository userRepository) {\n this.userRepository = userRepository;\n }\n\n public String getUserName(Long id) {\n User user = userRepository.findById(id);\n return user != null ? user.getName() : "Unknown";\n }\n}\n\n// اختبار باستخدام Mockito\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.mockito.Mockito.*;\nimport static org.junit.jupiter.api.Assertions.*;\n\n@ExtendWith(MockitoExtension.class)\npublic class UserServiceTest {\n\n @Mock\n private UserRepository userRepository;\n\n @Test\n public void testGetUserName() {\n // إنشاء كائن mock لـ UserRepository (يمكن عبر التعليمة @Mock)\n // UserRepository mockRepo = mock(UserRepository.class);\n\n // ضبط السلوك: عند استدعاء findById(1L) إرجاع مستخدم\n User mockUser = new User(1L, "Alice");\n when(userRepository.findById(1L)).thenReturn(mockUser);\n\n