Menguji implementasi Worker

WorkManager menyediakan API untuk pengujian Worker, ListenableWorker, dan varian ListenableWorker (CoroutineWorker dan RxWorker).

Menguji Pekerja

Anggaplah kita memiliki Worker yang terlihat seperti ini:

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();
        }
    }
}

Untuk menguji Worker ini, Anda dapat menggunakan TestWorkerBuilder. Builder ini membantu mem-build instance Worker yang dapat digunakan untuk tujuan pengujian logika bisnis.

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 juga dapat digunakan untuk menetapkan tag, seperti inputData atau runAttemptCount, sehingga Anda dapat memverifikasi status pekerja secara terpisah. Perhatikan contoh berikut, saat SleepWorker menggunakan durasi tidur sebagai data input dan bukan konstanta yang ditetapkan di pekerja:

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();
        }
    }
}

Di SleepWorkerTest, Anda dapat memberikan data input tersebut ke TestWorkerBuilder untuk memenuhi kebutuhan 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()));
    }
}

Untuk detail selengkapnya tentang API TestWorkerBuilder, baca halaman referensi untuk TestListenableWorkerBuilder, superclass TestWorkerBuilder.

Menguji ListenableWorker dan variannya

Untuk menguji ListenableWorker atau variannya (CoroutineWorker dan RxWorker), gunakan TestListenableWorkerBuilder. Perbedaan utama antara TestWorkerBuilder dan TestListenableWorkerBuilder adalah TestWorkerBuilder memungkinkan Anda menentukan latar belakang Executor yang digunakan untuk menjalankan Worker, sedangkan TestListenableWorkerBuilder bergantung pada logika thread implementasi ListenableWorker.

Misalnya, anggaplah kita perlu menguji CoroutineWorker yang terlihat seperti ini:

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

Untuk menguji SleepWorker, pertama-tama buat instance Pekerja menggunakan TestListenableWorkerBuilder, lalu panggil fungsi doWork dalam coroutine.

@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 logis sebagai builder coroutine untuk pengujian Anda agar setiap kode yang dijalankan secara asinkron akan berjalan secara paralel.

Menguji implementasi RxWorker mirip dengan menguji CoroutineWorker, karena TestListenableWorkerBuilder dapat menangani setiap subclass ListenableWorker. Pertimbangkan versi SleepWorker yang menggunakan RxJava dan bukan coroutine.

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);
    }
}

Versi SleepWorkerTest yang menguji RxWorker mungkin terlihat mirip dengan versi yang menguji CoroutineWorker. Anda menggunakan TestListenableWorkerBuilder yang sama, tetapi sekarang memanggil fungsi createWork RxWorker. createWork menampilkan Single yang dapat digunakan untuk memverifikasi perilaku pekerja. TestListenableWorkerBuilder menangani setiap kerumitan threading dan menjalankan kode pekerja Anda secara paralel.

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())));
        }
}