Pengujian integrasi dengan WorkManager

WorkManager menyediakan artefak work-testing yang membantu dalam pengujian pekerja Anda.

Penyiapan

Untuk menggunakan artefak work-testing, tambahkan sebagai dependensi androidTestImplementation di build.gradle.

Groovy

 dependencies {     def work_version = "2.5.0"      ...      // optional - Test helpers     androidTestImplementation "androidx.work:work-testing:$work_version" } 

Kotlin

 dependencies {     val work_version = "2.4.0"      ...      // optional - Test helpers     androidTestImplementation("androidx.work:work-testing:$work_version") } 

Untuk informasi penambahan dependensi selengkapnya, lihat bagian Mendeklarasikan dependensi pada Catatan rilis WorkManager.

Konsep

work-testing menyediakan implementasi WorkManager khusus untuk mode pengujian, yang diinisialisasi menggunakan WorkManagerTestInitHelper.

Artefak work-testing juga menyediakan SynchronousExecutor yang mempermudah penulisan pengujian secara sinkron, tanpa perlu menangani banyak thread, lock, atau latch.

Berikut ini contoh cara menggunakan semua class tersebut bersama-sama.

Kotlin

 @RunWith(AndroidJUnit4::class) class BasicInstrumentationTest {     @Before     fun setup() {         val context = InstrumentationRegistry.getTargetContext()         val config = Configuration.Builder()             .setMinimumLoggingLevel(Log.DEBUG)             .setExecutor(SynchronousExecutor())             .build()          // Initialize WorkManager for instrumentation tests.         WorkManagerTestInitHelper.initializeTestWorkManager(context, config)     } } 

Java

 @RunWith(AndroidJUnit4.class) public class BasicInstrumentationTest {     @Before     public void setup() {         Context context = InstrumentationRegistry.getTargetContext();         Configuration config = new Configuration.Builder()                 .setMinimumLoggingLevel(Log.DEBUG)                 .setExecutor(new SynchronousExecutor())                 .build();          // Initialize WorkManager for instrumentation tests.         WorkManagerTestInitHelper.initializeTestWorkManager(             context, config);     } } 

Menyusun Pengujian

Setelah WorkManager diinisialisasi dalam mode pengujian, Anda siap untuk menguji pekerja.

Misalnya, Anda memiliki EchoWorker yang mengharapkan inputData, dan sekadar menyalin (menggemakan) inputnya ke outputData.

Kotlin

 class EchoWorker(context: Context, parameters: WorkerParameters)    : Worker(context, parameters) {    override fun doWork(): Result {        return when(inputData.size()) {            0 - >Result.failure()            else - >Result.success(inputData)        }    } } 

Java

 public class EchoWorker extends Worker {   public EchoWorker(Context context, WorkerParameters parameters) {       super(context, parameters);   }    @NonNull   @Override   public Result doWork() {       Data input = getInputData();       if (input.size() == 0) {           return Result.failure();       } else {           return Result.success(input);       }   } } 

Pengujian Dasar

Berikut adalah Uji instrumentasi Android yang menguji EchoWorker. Poin utama yang dapat diambil di sini adalah menguji EchoWorker dalam mode pengujian sangat mirip dengan menggunakan EchoWorker dalam aplikasi sebenarnya.

Kotlin

 @Test @Throws(Exception::class) fun testSimpleEchoWorker() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      // Create request     val request = OneTimeWorkRequestBuilderE<choWorker(>)         .setInputData(input)         .build()      val workManager = WorkManager.getInstance(applicationContext)     // Enqueue and wait for result. This also runs the Worker synchronously     // because we are using a SynchronousExecutor.     workManager.enqueue(request).result.get()     // Get WorkInfo and outputData     val workInfo = workManager.getWorkInfoById(request.id).get()     val outputData = workInfo.outputData      // Assert     assertThat(workInfo.state, `is`(WorkInfo.State.SUCCEEDED))     assertThat(outputData, `is`(input)) } 

Java

 @Test public void testSimpleEchoWorker() throws Exception {    // Define input data    Data input = new Data.Builder()            .put(KEY_1, 1)            .put(KEY_2, 2)            .build();     // Create request    OneTimeWorkRequest request =        new OneTimeWorkRequest.Builder(EchoWorker.class)            .setInputData(input)            .build();     WorkManager workManager = WorkManager.getInstance(getApplicationContext());    // Enqueue and wait for result. This also runs the Worker synchronously    // because we are using a SynchronousExecutor.    workManager.enqueue(request).getResult().get();    // Get WorkInfo and outputData    WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get();    Data outputData = workInfo.getOutputData();     // Assert    assertThat(workInfo.getState(), is(WorkInfo.State.SUCCEEDED));    assertThat(outputData, is(input)); } 

Mari kita tulis pengujian lain yang memastikan bahwa saat EchoWorker tidak mendapatkan data input, Result yang diharapkan adalah Result.failure().

Kotlin

 @Test @Throws(Exception::class) fun testEchoWorkerNoInput() {    // Create request    val request = OneTimeWorkRequestBuilderE<choWorker(>)        .build()     val workManager = WorkManager.getInstance(applicationContext)    // Enqueue and wait for result. This also runs the Worker synchronously    // because we are using a SynchronousExecutor.    workManager.enqueue(request).result.get()    // Get WorkInfo    val workInfo = workManager.getWorkInfoById(request.id).get()     // Assert    assertThat(workInfo.state, `is`(WorkInfo.State.FAILED)) } 

Java

 @Test public void testEchoWorkerNoInput() throws Exception {   // Create request   OneTimeWorkRequest request =       new OneTimeWorkRequest.Builder(EchoWorker.class)          .build();    WorkManager workManager = WorkManager.getInstance(getApplicationContext());   // Enqueue and wait for result. This also runs the Worker synchronously   // because we are using a SynchronousExecutor.   workManager.enqueue(request).getResult().get();   // Get WorkInfo   WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get();    // Assert   assertThat(workInfo.getState(), is(WorkInfo.State.FAILED)); } 

Menyimulasikan batasan, penundaan, dan pekerjaan berkala

WorkManagerTestInitHelper menyediakan instance TestDriver yang dapat digunakan untuk menyimulasikan keterlambatan awal, kondisi saat batasan untuk instance ListenableWorker dan interval untuk instance PeriodicWorkRequest terpenuhi.

Menguji Penundaan Awal

Worker dapat mengalami penundaan awal. Untuk menguji EchoWorker dengan initialDelay, daripada menunggu initialDelay dalam pengujian, Anda dapat menggunakan TestDriver untuk menandai penundaan awal permintaan pekerjaan sebagai pekerjaan yang terpenuhi menggunakan setInitialDelayMet.

Kotlin

 @Test @Throws(Exception::class) fun testWithInitialDelay() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      // Create request     val request = OneTimeWorkRequestBuilderE<choWorker(>)         .setInputData(input)         .setInitialDelay(10, TimeUnit.SECONDS)         .build()      val workManager = WorkManager.getInstance(getApplicationContext())     // Get the TestDriver     val testDriver = WorkManagerTestInitHelper.getTestDriver()     // Enqueue     workManager.enqueue(request).result.get()     // Tells the WorkManager test framework that initial delays are now met.     testDriver.setInitialDelayMet(request.id)     // Get WorkInfo and outputData     val workInfo = workManager.getWorkInfoById(request.id).get()     val outputData = workInfo.outputData      // Assert     assertThat(workInfo.state, `is`(WorkInfo.State.SUCCEEDED))     assertThat(outputData, `is`(input)) } 

Java

 @Test public void testWithInitialDelay() throws Exception {   // Define input data   Data input = new Data.Builder()           .put(KEY_1, 1)           .put(KEY_2, 2)           .build();    // Create request   OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(EchoWorker.class)           .setInputData(input)           .setInitialDelay(10, TimeUnit.SECONDS)           .build();    WorkManager workManager = WorkManager.getInstance(myContext);   // Get the TestDriver   TestDriver testDriver = WorkManagerTestInitHelper.getTestDriver();   // Enqueue   workManager.enqueue(request).getResult().get();   // Tells the WorkManager test framework that initial delays are now met.   testDriver.setInitialDelayMet(request.getId());   // Get WorkInfo and outputData   WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get();   Data outputData = workInfo.getOutputData();    // Assert   assertThat(workInfo.getState(), is(WorkInfo.State.SUCCEEDED));   assertThat(outputData, is(input)); } 

Menguji Batasan

TestDriver juga dapat digunakan untuk menandai batasan menjadi terpenuhi menggunakan setAllConstraintsMet. Berikut ini contoh cara menguji Worker dengan batasan.

Kotlin

 @Test @Throws(Exception::class) fun testWithConstraints() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      val constraints = Constraints.Builder()         .setRequiredNetworkType(NetworkType.CONNECTED)         .build()      // Create request     val request = OneTimeWorkRequestBuilderE<choWorker(>)         .setInputData(input)         .setConstraints(constraints)         .build()      val workManager = WorkManager.getInstance(myContext)     val testDriver = WorkManagerTestInitHelper.getTestDriver()     // Enqueue     workManager.enqueue(request).result.get()     // Tells the testing framework that all constraints are met.     testDriver.setAllConstraintsMet(request.id)     // Get WorkInfo and outputData     val workInfo = workManager.getWorkInfoById(request.id).get()     val outputData = workInfo.outputData      // Assert     assertThat(workInfo.state, `is`(WorkInfo.State.SUCCEEDED))     assertThat(outputData, `is`(input)) } 

Java

 @Test public void testWithConstraints() throws Exception {     // Define input data     Data input = new Data.Builder()             .put(KEY_1, 1)             .put(KEY_2, 2)             .build();      // Define constraints     Constraints constraints = new Constraints.Builder()             .setRequiresDeviceIdle(true)             .build();      // Create request     OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(EchoWorker.class)             .setInputData(input)             .setConstraints(constraints)             .build();      WorkManager workManager = WorkManager.getInstance(myContext);     TestDriver testDriver = WorkManagerTestInitHelper.getTestDriver();     // Enqueue     workManager.enqueue(request).getResult().get();     // Tells the testing framework that all constraints are met.     testDriver.setAllConstraintsMet(request.getId());     // Get WorkInfo and outputData     WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get();     Data outputData = workInfo.getOutputData();      // Assert     assertThat(workInfo.getState(), is(WorkInfo.State.SUCCEEDED));     assertThat(outputData, is(input)); } 

Menguji Pekerjaan Berkala

TestDriver juga memperlihatkan setPeriodDelayMet yang dapat digunakan untuk menunjukkan bahwa interval selesai. Berikut adalah contoh saat setPeriodDelayMet digunakan.

Kotlin

 @Test @Throws(Exception::class) fun testPeriodicWork() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      // Create request     val request = PeriodicWorkRequestBuilderE<choWorker(>15, MINUTES)         .setInputData(input)         .build()      val workManager = WorkManager.getInstance(myContext)     val testDriver = WorkManagerTestInitHelper.getTestDriver()     // Enqueue and wait for result.     workManager.enqueue(request).result.get()     // Tells the testing framework the period delay is met     testDriver.setPeriodDelayMet(request.id)     // Get WorkInfo and outputData     val workInfo = workManager.getWorkInfoById(request.id).get()      // Assert     assertThat(workInfo.state, `is`(WorkInfo.State.ENQUEUED)) } 

Java

 @Test public void testPeriodicWork() throws Exception {     // Define input data     Data input = new Data.Builder()             .put(KEY_1, 1)             .put(KEY_2, 2)             .build();      // Create request     PeriodicWorkRequest request =             new PeriodicWorkRequest.Builder(EchoWorker.class, 15, MINUTES)             .setInputData(input)             .build();      WorkManager workManager = WorkManager.getInstance(myContext);     TestDriver testDriver = WorkManagerTestInitHelper.getTestDriver();     // Enqueue and wait for result.     workManager.enqueue(request).getResult().get();     // Tells the testing framework the period delay is met     testDriver.setPeriodDelayMet(request.getId());     // Get WorkInfo and outputData     WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get();      // Assert     assertThat(workInfo.getState(), is(WorkInfo.State.ENQUEUED)); }