0Pricing
Kotlin Academy · درس

اختبار Coroutines

اختبروا الدوال المعلّقة

اختبار Coroutines درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

لماذا يختلف اختبار coroutines

تعمل coroutines بشكل غير متزامن، وقد تستخدم التأخيرات. وتحتاج الاختبارات إلى وقت يمكن التحكم فيه وطريقة لانتظار اكتمال الدوال المعلّقة.

توفّر مكتبة kotlinx-coroutines-test ذلك تمامًا.

إضافة مكتبة الاختبار

أضف artifact اختبار coroutines إلى اعتماديات الاختبار.

dependencies {
    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1")
}

runTest

يمثّل runTest نقطة الدخول. فهو يشغّل جسم اختبار coroutine وينتظر تلقائيًا اكتمال جميع coroutines التابعة.

import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test

class FetchTest {
    @Test
    fun fetches() = runTest {
        // suspend calls allowed here
    }
}

الوقت الافتراضي

داخل runTest، يتم تجاوز استدعاءات delay باستخدام الوقت الافتراضي. إذ يكتمل تأخير مدته 10 ثوانٍ فورًا، مع الحفاظ على الترتيب.

import kotlinx.coroutines.delay
import kotlinx.coroutines.test.runTest

// runTest {
//     delay(10_000) // returns immediately
// }

تقديم الوقت يدويًا

يتيح لك مجدول الاختبار تقديم الوقت عمدًا باستخدام advanceTimeBy، وتنفيذ العمل المعلّق باستخدام runCurrent.

import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runCurrent

// runTest {
//     launch { delay(1000); println("done") }
//     advanceTimeBy(1000)
//     runCurrent()
// }

موزّعات الاختبار

يضع StandardTestDispatcher coroutines في قائمة انتظار حتى تقدّم الوقت. بينما ينفّذها UnconfinedTestDispatcher فورًا. اختر بينهما بناءً على مستوى التحكم الذي تحتاج إليه.

import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.UnconfinedTestDispatcher

val standard = StandardTestDispatcher()
val unconfined = UnconfinedTestDispatcher()

حقن موزّع

ينبغي للرمز المستخدم في الإنتاج أن يستقبل موزّعًا بدلًا من تثبيت Dispatchers.IO داخله. ويمكن للاختبارات عندئذٍ حقن موزّع اختبار.

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class Service(private val io: CoroutineDispatcher = Dispatchers.IO) {
    suspend fun load(): String = withContext(io) { "data" }
}

استبدال Dispatchers.Main

في الرمز المصمم بأسلوب Android، استبدل موزّع Main باستخدام Dispatchers.setMain(testDispatcher)، ثم أعد ضبطه بعد ذلك.

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.test.setMain
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.StandardTestDispatcher

// Dispatchers.setMain(StandardTestDispatcher())
// ... test ...
// Dispatchers.resetMain()

اختبار دالة معلّقة

يمكن استدعاء الدالة المعلّقة والتحقق منها مباشرة داخل runTest.

import kotlinx.coroutines.delay
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals

suspend fun compute(): Int { delay(1000); return 42 }

// @Test fun computes() = runTest {
//     assertEquals(42, compute())
// }

اختبار Flows

اجمع Flow وتحقق من القيم المنبعثة. وتجعل مكتبة Turbine اختبار التدفقات أكثر وضوحًا ونظافة.

import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals

// @Test fun emits() = runTest {
//     val values = flowOf(1, 2, 3).toList()
//     assertEquals(listOf(1, 2, 3), values)
// }

مقطع coroutine قابل للتشغيل

خارج الاختبارات، يربط runBlocking الرمز المعلّق بدالة main عادية. ويوضح ذلك الدالة المعلّقة التي يجري اختبارها.

import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.delay

suspend fun compute(): Int { delay(100); return 42 }

fun main() = runBlocking {
    println(compute())
}

تحقق سريع

تستدعي دالة معلّقة delay(5000). لماذا ينتهي اختبار يستخدم runTest بسرعة تكاد تكون فورية؟

مراجعة

يمكنك اختبار coroutines بشكل موثوق:

  • يشغّل runTest الرمز المعلّق وينتظر coroutines التابعة
  • يتجاوز الوقت الافتراضي التأخيرات؛ ويمكنك تقديم الوقت يدويًا عند الحاجة
  • احقن الموزّعات؛ واستخدم setMain/resetMain
  • اختبر التدفقات بجمعها (أو باستخدام Turbine)

وبذلك تكتمل دورة الاختبار.

الأسئلة الشائعة

هل درس «اختبار Coroutines» مجاني؟

نعم — نص درس «اختبار Coroutines» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

ماذا ستتعلم في «اختبار Coroutines»؟

اختبروا الدوال المعلّقة تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟

لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «اختبار Coroutines»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟

نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. كتابة الاختبارات باستخدام JUnit5
  2. التوكيدات
  3. المحاكاة باستخدام MockK
  4. اختبار Coroutines
← العودة إلى Kotlin Academy