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())); } }
برای جزئیات بیشتر در مورد TestWorkerBuilder API، به صفحه مرجع 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()))); } }