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