הטמעת Worker

WorkManager מספק ממשקי API לבדיקה של Worker, ListenableWorker, וגם ListenableWorker וריאנטים (CoroutineWorker ו-RxWorker).

עובדי בדיקה

נניח שיש לנו Worker שנראה כך:

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

כדי לבדוק את הWorker הזה, אפשר להשתמש TestWorkerBuilder. הזה עוזר לפתח מכונות של Worker שיכולות לשמש ובדיקת הלוגיקה העסקית.

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 = TestWorkerBuilderS<leepWorker(>
            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 גם כדי להגדיר תגים, כמו inputData או runAttemptCount, כדי שאפשר יהיה לאמת את מצב העובד בנפרד. נקודות שכדאי להעלות דוגמה שבה SleepWorker לוקחת את משך השינה כנתוני קלט במקום שהוא קבוע שמוגדר ב-Worker:

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

ב-SleepWorkerTest, אפשר לספק את נתוני הקלט האלה TestWorkerBuilder כדי לענות על הצרכים של 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 = TestWorkerBuilderS<leepWorker(>
            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()));
    }
}

לפרטים נוספים על 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 במקום בקורוטינים.

Kotlin

class SleepWorker(
    context: Context,
    parameters: WorkerParameters
) : RxWorker(context, parameters) {
    override fun createWork(): SingleR<esult >{
        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 SingleR<esult >createWork() {
        return Single.just(Result.success())
                .delay(1000L, TimeUnit.MILLISECONDS);
    }
}

גרסה של SleepWorkerTest שבודקת RxWorker עשויה להיראות דומה גרסה שבדקה CoroutineWorker. אתם משתמשים באותה TestListenableWorkerBuilder, אבל עכשיו אפשר להתקשר ל-createWork של RxWorker מותאמת אישית. הפונקציה createWork מחזירה ערך Single שאפשר להשתמש בו כדי לאמת את של העובד שלך. TestListenableWorkerBuilder מטפל בכל השרשורים מורכבים יותר, ומפעיל את קוד ה-worker במקביל.

Kotlin

@RunWith(AndroidJUnit4::class)
class SleepWorkerTest {
    private lateinit var context: Context

    @Before
    fun setUp() {
        context = ApplicationProvider.getApplicationContext()
    }

    @Test
    fun testSleepWorker() {
        val worker = TestListenableWorkerBuilderS<leepWorker(>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())));
        }
}