اختبار مشغِّل التطبيق

توفّر WorkManager واجهات برمجة تطبيقات لاختبار Worker وListenableWorker وإصدارات ListenableWorker (CoroutineWorker وRxWorker).

مشغِّلو الاختبارات

لنفترض أن لدينا Worker الذي يبدو على النحو التالي:

Kotlin


class SleepWorker(context: Context, parameters: WorkerParameters) :
    Worker(context, parameters) {

    override fun doWork(): Result {
        // Sleep on a background thread.
        Thread.sleep(1000)
        return Result.success()
    }
}

Java


public class SleepWorker extends Worker {
    public SleepWorker(
            @NonNull Context context,
            @NonNull WorkerParameters workerParameters) {
        super(context, workerParameters);
    }

    @NonNull
    @Override
    public Result doWork() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ignore) {
return Result.success();
        }
    }
}

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

Kotlin


// Kotlin code uses the TestWorkerBuilder extension to build
// the Worker
@RunWith(AndroidJUnit4::class)
class SleepWorkerTest {
    private lateinit var context: Context
    private lateinit var executor: Executor

    @Before
    fun setUp() {
        context = ApplicationProvider.getApplicationContext()
        executor = Executors.newSingleThreadExecutor()
    }

    @Test
    fun testSleepWorker() {
        val worker = TestWorkerBuilder<SleepWorker>(
            context = context,
            executor = executor
        ).build()

        val result = worker.doWork()
        assertThat(result, `is`(Result.success()))
    }
}

Java


@RunWith(AndroidJUnit4.class)
public class SleepWorkerJavaTest {
    private Context context;
    private Executor executor;

    @Before
    public void setUp() {
        context = ApplicationProvider.getApplicationContext();
        executor = Executors.newSingleThreadExecutor();
    }

    @Test
    public void testSleepWorker() {
        SleepWorker worker =
                (SleepWorker) TestWorkerBuilder.from(context,
                        SleepWorker.class,
                        executor)
                        .build();

        Result result = worker.doWork();
        assertThat(result, is(Result.success()));
    }
}

يمكن أيضًا استخدام TestWorkerBuilder لضبط العلامات، مثل inputData أو runAttemptCount، لتتمكّن من التحقّق من حالة العامل بمعزل عن الآخر. اطّلِع على مثال يتم فيه استخدام السمة SleepWorker في مدة النوم كبيانات المدخلة بدلاً من كونها قيمة ثابتة لدى العامل:

Kotlin


class SleepWorker(context: Context, parameters: WorkerParameters) :
    Worker(context, parameters) {

    override fun doWork(): Result {
        // Sleep on a background thread.
        val sleepDuration = inputData.getLong(SLEEP_DURATION, 1000)
        Thread.sleep(sleepDuration)
        return Result.success()
    }

    companion object {
        const val SLEEP_DURATION = "SLEEP_DURATION"
    }
}

Java


public class SleepWorker extends Worker {
    public static final String SLEEP_DURATION = "SLEEP_DURATION";

    public SleepWorker(
            @NonNull Context context,
            @NonNull WorkerParameters workerParameters) {
        super(context, workerParameters);
    }

    @NonNull
    @Override
    public Result doWork() {
        try {
            long duration = getInputData().getLong(SLEEP_DURATION, 1000);
            Thread.sleep(duration);
        } catch (InterruptedException ignore) {
       return Result.success();
        }
    }
}

في SleepWorkerTest، يمكنك توفير هذه البيانات التي تم إدخالها إلى TestWorkerBuilder لتلبية احتياجات SleepWorker.

Kotlin


// Kotlin code uses the TestWorkerBuilder extension to build
// the Worker
@RunWith(AndroidJUnit4::class)
class SleepWorkerTest {
    private lateinit var context: Context
    private lateinit var executor: Executor

    @Before
    fun setUp() {
        context = ApplicationProvider.getApplicationContext()
        executor = Executors.newSingleThreadExecutor()
    }

    @Test
    fun testSleepWorker() {
        val worker = TestWorkerBuilder<SleepWorker>(
            context = context,
            executor = executor,
            inputData = workDataOf("SLEEP_DURATION" to 1000L)
        ).build()

        val result = worker.doWork()
        assertThat(result, `is`(Result.success()))
    }
}

Java


@RunWith(AndroidJUnit4.class)
public class SleepWorkerJavaTest {
    private Context context;
    private Executor executor;

    @Before
    public void setUp() {
        context = ApplicationProvider.getApplicationContext();
        executor = Executors.newSingleThreadExecutor();
    }

    @Test
    public void testSleepWorker() {
        Data inputData = new Data.Builder()
                .putLong("SLEEP_DURATION", 1000L)
                .build();

        SleepWorker worker =
                (SleepWorker) TestWorkerBuilder.from(context,
                        SleepWorker.class, executor)
                        .setInputData(inputData)
                        .build();

        Result result = worker.doWork();
        assertThat(result, is(Result.success()));
    }
}

للمزيد من التفاصيل حول واجهة برمجة تطبيقات TestWorkerBuilder، يمكنك الاطّلاع على الصفحة المرجعية الخاصة بـ TestListenableWorkerBuilder، وهي الفئة المتميّزة لـ TestWorkerBuilder.

اختبار ListenableWorker ومتغيراته

لاختبار ListenableWorker أو صيغه (CoroutineWorker وRxWorker)، استخدِم TestListenableWorkerBuilder. يكمن الاختلاف الرئيسي بين TestWorkerBuilder وTestListenableWorkerBuilder في أنّ TestWorkerBuilder يتيح لك تحديد الخلفية Executor المُستخدَمة لتشغيل Worker، في حين تعتمد TestListenableWorkerBuilder على منطق سلاسل المحادثات في تنفيذ ListenableWorker.

على سبيل المثال، لنفترض أنّنا بحاجة إلى اختبار CoroutineWorker على النحو التالي:

class SleepWorker(context: Context, parameters: WorkerParameters) :
    CoroutineWorker(context, parameters) {
    override suspend fun doWork(): Result {
        delay(1000L) // milliseconds
        return Result.success()
    }
}

لاختبار SleepWorker، ننشئ أولاً مثيلاً للعامل باستخدام TestListenableWorkerBuilder ثم نستدعي الدالة doWork ضمن الكوروتين.

@RunWith(AndroidJUnit4::class)
class SleepWorkerTest {
    private lateinit var context: Context

    @Before
    fun setUp() {
        context = ApplicationProvider.getApplicationContext()
    }

    @Test
    fun testSleepWorker() {
        val worker = TestListenableWorkerBuilder<SleepWorker>(context).build()
        runBlocking {
            val result = worker.doWork()
            assertThat(result, `is`(Result.success()))
        }
    }
}

تُعدّ runBlocking أداة إنشاء الكوروتينات اللازمة لاختباراتك، وبالتالي يتم تشغيل أي رمز يتم تنفيذه بشكل غير متزامن بالتوازي.

يشبه اختبار تنفيذ RxWorker اختبار CoroutineWorker، لأنّ TestListenableWorkerBuilder يمكنها التعامل مع أي فئة فرعية من ListenableWorker. جرِّب إصدارًا من SleepWorker يستخدم RxJava بدلاً من الكوروتين.

Kotlin


class SleepWorker(
    context: Context,
    parameters: WorkerParameters
) : RxWorker(context, parameters) {
    override fun createWork(): Single<Result> {
        return Single.just(Result.success())
            .delay(1000L, TimeUnit.MILLISECONDS)
    }
}

Java


public class SleepWorker extends RxWorker {
    public SleepWorker(@NonNull Context appContext, 
@NonNull WorkerParameters workerParams) {
        super(appContext, workerParams);
    }

    @NonNull
    @Override
    public Single<Result> createWork() {
        return Single.just(Result.success())
                .delay(1000L, TimeUnit.MILLISECONDS);
    }
}

إنّ إصدار SleepWorkerTest الذي يختبر RxWorker قد يبدو مشابهًا للإصدار الذي اختبر CoroutineWorker. أنت تستخدم TestListenableWorkerBuilder نفسها ولكنك تستدعي الآن دالة createWork في RxWorker. تعرض createWork عنصر Single يمكنك استخدامه للتحقّق من سلوك عاملك. تعالج TestListenableWorkerBuilder أي تعقيدات في سلاسل التعليمات وتنفِّذ رمز العامل بالتوازي.

Kotlin


@RunWith(AndroidJUnit4::class)
class SleepWorkerTest {
    private lateinit var context: Context

    @Before
    fun setUp() {
        context = ApplicationProvider.getApplicationContext()
    }

    @Test
    fun testSleepWorker() {
        val worker = TestListenableWorkerBuilder<SleepWorker>(context).build()
        worker.createWork().subscribe { result ->
            assertThat(result, `is`(Result.success()))
        }
    }
}

Java


@RunWith(AndroidJUnit4.class)
public class SleepWorkerTest {
    private Context context;

    @Before
    public void setUp() {
        context = ApplicationProvider.getApplicationContext();
    }

    @Test
    public void testSleepWorker() {
        SleepWorker worker = TestListenableWorkerBuilder.from(context, SleepWorker.class)
                .build();
        worker.createWork().subscribe(result ->
                assertThat(result, is(Result.success())));
        }
}