Реализация Testing Worker

WorkManager предоставляет API для тестирования Worker , ListenableWorker и вариантов ListenableWorker ( CoroutineWorker и RxWorker ).

Тестирующие работники

Допустим, у нас есть Worker , который выглядит так:

Котлин

  class SleepWorker(context: Context, parameters: WorkerParameters) :     Worker(context, parameters) {      override fun doWork(): Result {         // Sleep on a background thread.         Thread.sleep(1000)         return Result.success()     } }  

Ява

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

Ява

  @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 принимает продолжительность сна в качестве входных данных, а не как константу, определенную в рабочем процессе:

Котлин

  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"     } }  

Ява

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

Ява

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

Дополнительные сведения об API 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 , мы сначала создаем экземпляр Worker с помощью 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 вместо сопрограмм.

Котлин

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

Ява

  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 справляется с любыми сложностями потоковой обработки и параллельно выполняет ваш рабочий код.

Котлин

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

Ява

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