Moq لـ C# (.NET): دليل شامل مع أمثلة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

ما هو Moq ولماذا هو مطلوب؟

\n\n

Moq (تُنطق "موك") هي مكتبة شائعة لإنشاء كائنات mock (كائنات وهمية) في C# (.NET). وهي جزء من نظام الاختبارات الوحدوية وتُستخدم لعزل الكود المختبر عن تبعياته.

\n\n

في التطبيقات الحقيقية، غالبًا ما تعتمد الفئات على فئات أخرى: قواعد البيانات، خدمات الويب، نظام الملفات، API لخدمات الطرف الثالث. عند كتابة اختبارات وحدوية، لا نريد اختبار هذه التبعيات الخارجية — بل نريد فقط التحقق من منطق الفئة الخاصة بنا. يسمح Moq بإنشاء كائنات "مزيفة" (mock) تحاكي سلوك التبعيات الحقيقية، ولكنها تحت السيطرة الكاملة للاختبار.

\n\n

سيناريوهات الاستخدام الرئيسية لـ Moq:

\n
    \n
  • عزل الاختبارات: اختبار فئة واحدة دون تشغيل قاعدة بيانات أو خدمات خارجية.
  • \n
  • التحقق من التفاعلات: التأكد من استدعاء طريقة بالوسائط الصحيحة، وعدد معين من المرات.
  • \n
  • تعيين القيم المُرجعة: جعل التبعية تُرجع البيانات المطلوبة للتحقق من المنطق.
  • \n
  • محاكاة الاستثناءات: التحقق من كيفية معالجة الكود للأخطاء من الأنظمة الخارجية.
  • \n
\n\n

يعمل Moq مع الواجهات والطرق الافتراضية للفئات. هذا هو القيد الرئيسي: لا يمكنك عمل mock لطريقة ثابتة أو طريقة غير افتراضية.

\n\n

تثبيت Moq

\n\n

يتم توزيع Moq عبر NuGet — مدير الحزم لـ .NET. يمكن تثبيته بعدة طرق:

\n\n

عبر .NET CLI (موصى به)

\n
dotnet add package Moq
\n\n

عبر Package Manager Console (Visual Studio)

\n
Install-Package Moq
\n\n

عبر واجهة NuGet Package Manager UI

\n

في Visual Studio: انقر بزر الماوس الأيمن على المشروع → Manage NuGet Packages → ابحث عن "Moq" → تثبيت

\n\n

المتطلبات: .NET Framework 4.5+ أو .NET Core 2.0+ / .NET 5+

\n\n

بداية سريعة: أول اختبار مع Moq

\n\n

لنفترض أن لدينا واجهة مستودع وخدمة تستخدمها:

\n\n
public interface IUserRepository\n{\n    User GetUserById(int id);\n    void SaveUser(User user);\n}\n\npublic class UserService\n{\n    private readonly IUserRepository _repository;\n\n    public UserService(IUserRepository repository)\n    {\n        _repository = repository;\n    }\n\n    public string GetUserName(int userId)\n    {\n        var user = _repository.GetUserById(userId);\n        return user?.Name ?? "Unknown";\n    }\n}\n\npublic class User\n{\n    public int Id { get; set; }\n    public string Name { get; set; }\n}
\n\n

الآن سنكتب اختبارًا باستخدام Moq:

\n\n
using Moq;\nusing Xunit;\n\npublic class UserServiceTests\n{\n    [Fact]\n    public void GetUserName_WhenUserExists_ReturnsUserName()\n    {\n        // Arrange\n        var mockRepo = new Mock<IUserRepository>();\n        mockRepo.Setup(repo => repo.GetUserById(1))\n                .Returns(new User { Id = 1, Name = "Alice" });\n\n        var service = new UserService(mockRepo.Object);\n\n        // Act\n        var result = service.GetUserName(1);\n\n        // Assert\n        Assert.Equal("Alice", result);\n        mockRepo.Verify(repo => repo.GetUserById(1), Times.Once);\n    }\n}
\n\n

تحليل المثال:

\n
    \n
  1. new Mock<IUserRepository>() — إنشاء كائن mock للواجهة.
  2. \n
  3. .Setup(...) — تكوين السلوك: عند استدعاء GetUserById(1)، إرجاع المستخدم Alice.
  4. \n
  5. mockRepo.Object — الحصول على الكائن "المزيف" الذي نمرره إلى الخدمة.
  6. \n
  7. mockRepo.Verify(...) — التحقق من أن الطريقة تم استدعاؤها مرة واحدة بالضبط.
  8. \n
\n\n

الطرق والوظائف الأساسية لـ Moq

\n\n

1. Mock<T>.Setup()

\n

ما يفعله: يكوّن سلوك الط

توصيات