اختبار التكامل في C# مع Docker: من الألف إلى الياء
\n\nاختبار التكامل هو مرحلة حاسمة في تطوير أي تطبيق جاد بلغة C#. فهو يتحقق من كيفية عمل المكونات المختلفة للنظام (قاعدة البيانات، واجهات API الخارجية، أنظمة الملفات) معًا. ومع ذلك، غالبًا ما يصبح إعداد بيئة الاختبار كابوسًا: تحتاج إلى تشغيل خوادم حقيقية، وتنظيف البيانات بعد الاختبارات، والتعامل مع عدم استقرار البيئة. يحل Docker هذه المشكلات من خلال توفير حاويات خفيفة ومعزولة وقابلة للتكرار. في هذه المقالة، سنشرح كيفية إعداد اختبار التكامل في C# مع Docker من الصفر إلى خط أنابيب عمل كامل.
\n\nلماذا يعتبر Docker مثاليًا لاختبارات التكامل في C#؟
\n\nالنهج التقليدي هو استخدام قواعد بيانات SQL Server المحلية أو محاكيات الخدمات الخارجية. يؤدي هذا إلى مشاكل:
\n- \n
- تلوث البيانات: تترك الاختبارات بيانات غير مرغوب فيها في قاعدة البيانات، مما يؤثر على الاختبارات الأخرى. \n
- عدم توافق البيئات: إصدار نظام إدارة قواعد البيانات على جهاز المطور يختلف عن إصداره على خادم CI. \n
- صعوبة التشغيل المتوازي: تتعارض الاختبارات على المنافذ والموارد. \n
يحل Docker هذه المشكلة ببساطة: يحصل كل اختبار (أو مجموعة اختبارات) على حاوية معزولة خاصة به مع الإصدار المطلوب من قاعدة البيانات أو Redis أو خدمة أخرى. الحاويات خفيفة، وتُشغل في ثوانٍ، ويتم تدميرها بشكل مضمون بعد انتهاء الاختبارات. بالنسبة لمطوري .NET، هذا مهم بشكل خاص بفضل مكتبة Testcontainers for .NET التي تؤتمت إدارة الحاويات مباشرة من كود الاختبارات.
\n\nإعداد المشروع: إضافة Docker إلى اختبارات C#
\n\nلنبدأ بإنشاء مشروع يحتوي على اختبارات التكامل. لنفترض أن لدينا واجهة برمجة تطبيقات ويب على .NET 8 تعمل مع PostgreSQL. نحتاج إلى اختبار نقطة نهاية إنشاء المستخدم.
\n\nالخطوة 1: تثبيت حزم NuGet
\nأضف الحزم التالية إلى مشروع الاختبار:
\ndotnet add package Testcontainers.PostgreSql\ndotnet add package Microsoft.AspNetCore.Mvc.Testing\ndotnet add package FluentAssertions\n\nTestcontainers.PostgreSql هي غلاف فوق Docker SDK يدير حاويات PostgreSQL. Microsoft.AspNetCore.Mvc.Testing تسمح بتشغيل تطبيق الويب في الذاكرة للاختبار.
الخطوة 2: إنشاء فئة أساسية للاختبارات
\nلننشئ فئة مجردة تقوم بتشغيل حاوية قاعدة البيانات قبل الاختبارات:
\nusing Testcontainers.PostgreSql;\nusing Xunit;\n\npublic abstract class IntegrationTestBase : IAsyncLifetime\n{\n private readonly PostgreSqlContainer _postgresContainer;\n\n protected string ConnectionString => _postgresContainer.GetConnectionString();\n\n protected IntegrationTestBase()\n {\n _postgresContainer = new PostgreSqlBuilder()\n .WithImage("postgres:16-alpine")\n .WithDatabase("testdb")\n .WithUsername("test")\n .WithPassword("test123")\n .Build();\n }\n\n public async Task InitializeAsync()\n {\n await _postgresContainer.StartAsync();\n }\n\n public async Task DisposeAsync()\n {\n await _postgresContainer.StopAsync();\n }\n}\n\nهذه الفئة تطبق IAsyncLifetime من xUnit، مما يضمن تشغيل الحاوية قبل جميع الاختبارات وإيقافها بعدها. يتم الحصول على ConnectionString ديناميكيًا من الحاوية - يمكن أن يكون المنفذ أي منفذ متاح.
الخطوة 3: كتابة اختبار باستخدام Testcontainers و WebApplicationFactory
\nالآن لنكتب الاختبار نفسه. سنستخدم WebApplicationFactory لإنشاء عميل HTTP للاختبار:
using Microsoft.AspNetCore.Mvc.Testing;\nusing FluentAssertions;\nusing System.Net.Http.Json;\n\npublic class UserApiTests : IntegrationTestBase\n{\n private readonly WebApplicationFactory<Program> _factory;\n\n public UserApiTests()\n