mockito fluttermockito flutter

تخيل أنك تكتب تطبيقًا يستخدم قاعدة بيانات حقيقية أو يستدعي واجهة برمجية (API) عبر الإنترنت.
لكن أثناء اختبار الكود، الاتصال بالإنترنت بطيء، أو السيرفر معطّل، أو بياناتك الحقيقية حساسة ولا يمكن استخدامها في بيئة تجريبية.
فماذا تفعل؟

هل تتوقف عن الاختبار؟ طبعًا لا.
هنا يأتي دور أحد أقوى الأساليب في عالم الاختبار: المحاكاة (Mocking) والتعويض (Stubbing).
إنهما السحر الذي يسمح لك باختبار كودك كما لو كان العالم من حوله حقيقيًا، دون الحاجة لأي خدمات خارجية.


ما المقصود بالمحاكاة والتعويض؟

قبل أن ندخل في التفاصيل، لنفهم الفكرة ببساطة:

  • المحاكاة (Mock):
    هي إنشاء كائن مزيف (Fake Object) يقلّد كائنًا حقيقيًا مثل قاعدة بيانات أو خدمة API، بحيث يمكننا التحكم في استجاباته أثناء الاختبار.
  • التعويض (Stub):
    هو تزويد الكائن المزيف بردود محددة مسبقًا عندما يتم استدعاؤه.

بعبارة أخرى:

المحاكاة تعني “تقليد السلوك”، والتعويض يعني “تحديد الرد”.


لماذا نستخدمهما في Flutter؟

لأن اختبارات الوحدة وواجهة المستخدم يجب أن تكون سريعة، مستقلة، ولا تعتمد على الإنترنت أو الأجهزة الحقيقية.
لكن تطبيقات Flutter غالبًا تعتمد على مكونات خارجية مثل:

  • Firebase أو APIs.
  • قواعد بيانات مثل SQLite.
  • Plugins للتخزين أو الكاميرا أو الموقع.

بدون المحاكاة، لن يمكنك اختبار الكود بسهولة، لأن هذه الخدمات قد تفشل أو تتطلب إعدادات معقدة.
لذلك، نستخدم مكتبات مثل Mockito لمحاكاة هذه التبعيات والتحكم في سلوكها.


⚙️ مكتبة Mockito: صديق المطور في الاختبارات

Mockito هي مكتبة Dart شهيرة تُستخدم لإنشاء كائنات مزيفة.
تعمل عن طريق “تغليف” الكائن الحقيقي وإنشاء نسخة تتحكم أنت فيها أثناء الاختبار.

للتثبيت، أضف التالي إلى ملف pubspec.yaml:

dev_dependencies:
  mockito: ^5.4.2
  build_runner: ^2.4.6

مثال عملي: اختبار خدمة مستخدم

افترض أن لدينا كودًا بسيطًا:

class UserService {
  Future<String> fetchUserName() async {
    // تستدعي API حقيقي عادةً
    await Future.delayed(Duration(seconds: 1));
    return 'Ahmed';
  }
}

الآن نريد اختباره دون الحاجة إلى أي API حقيقي.
نقوم بإنشاء mock class:

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';

class MockUserService extends Mock implements UserService {}

void main() {
  test('يجب أن يُعيد اسم المستخدم من الكائن المزيف', () async {
    final mockService = MockUserService();

    // نحدد السلوك المتوقع (Stub)
    when(mockService.fetchUserName()).thenAnswer((_) async => 'Ali');

    // نتحقق من النتيجة
    final result = await mockService.fetchUserName();
    expect(result, 'Ali');
  });
}

النتيجة: تم اختبار الكود بنجاح دون الحاجة لأي اتصال خارجي.


ما الفرق بين Mock وFake وStub؟

المصطلحالمعنىالاستخدام
Mockكائن مزيف يسجّل الاستدعاءات ويتحقق من السلوكعند اختبار تفاعل الكود
Fakeنسخة مبسطة من الكائن الحقيقيعند الحاجة إلى بيانات تجريبية
Stubكائن مزيف يعيد استجابات محددةعند اختبار النتائج فقط

اختبار التفاعلات باستخدام verify()

يمكنك أيضًا التأكد من أن الكائن تم استدعاؤه بالطريقة الصحيحة:

verify(mockService.fetchUserName()).called(1);

إذا لم يتم استدعاء الدالة أو تم استدعاؤها أكثر من مرة، يفشل الاختبار فورًا.


مثال متقدم: محاكاة Repository كامل

لنفترض أنك تملك طبقة UserRepository تتعامل مع API.
باستخدام Mockito، يمكنك اختبار منطق التعامل مع البيانات دون الاعتماد على API نفسه.

class UserRepository {
  final UserService service;
  UserRepository(this.service);

  Future<String> getUserGreeting() async {
    final name = await service.fetchUserName();
    return 'مرحباً $name!';
  }
}

void main() {
  test('يجب أن يعيد الترحيب الصحيح', () async {
    final mockService = MockUserService();
    when(mockService.fetchUserName()).thenAnswer((_) async => 'Laila');

    final repo = UserRepository(mockService);
    expect(await repo.getUserGreeting(), 'مرحباً Laila!');
  });
}

بهذه الطريقة، تختبر منطق الطبقات العليا من التطبيق بثقة كاملة، دون الحاجة لأي خوادم أو اتصالات فعلية.


أدوات إضافية للمحاكاة في Flutter

  • mocktail: بديل بسيط عن Mockito لا يتطلب توليد ملفات.
  • fake_async: لاختبار الأكواد التي تعتمد على مؤقتات (timers).
  • http_mock_adapter: لمحاكاة استجابات Dio وطلبات HTTP.

الخلاصة

المحاكاة والتعويض هما السلاح السري لكل مطور Flutter محترف.
بفضلهما، يمكنك اختبار الكود في بيئة آمنة، سريعة، ومنفصلة عن العالم الخارجي — دون أي خوف من بطء الإنترنت أو فشل الخوادم.

ابدأ بإضافة Mockito اليوم إلى مشروعك، وستكتشف كم يصبح الاختبار ممتعًا وسهلًا عندما تكون كل الأمور تحت سيطرتك.

تذكّر: المطور الذكي لا يختبر الكود فحسب، بل يتحكم في عالمه التجريبي أيضًا.


By احمد علي

مطور تطبيقات هواتف ذكية باستخدام Flutter، وصانع محتوى تقني يكتب عن الذكاء الاصطناعي والبرمجة وتطورات التكنولوجيا الحديثة. أسعى لتبسيط الأفكار المعقدة ومشاركة خبرتي مع المهتمين بالمجال.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *