WorkManager udostępnia interfejsy API do testowania Worker,
ListenableWorker oraz
ListenableWorker wariantu
(CoroutineWorker
i RxWorker).
Instancje robocze
Załóżmy, że mamy Worker, który wygląda tak:
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(); } } }
Aby przetestować to urządzenie (Worker), możesz użyć
TestWorkerBuilder Ten
kreator pomaga tworzyć instancje Worker, które można wykorzystać
testowania logiki biznesowej.
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 = TestWorkerBuilder<SleepWorker>( 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 może też służyć do ustawiania tagów, np. inputData lub
runAttemptCount, aby umożliwić sprawdzanie oddzielnie stanu instancji roboczej. Rozważ
Przykład, w którym SleepWorker traktuje czas trwania snu jako dane wejściowe
zamiast być stałą zdefiniowaną w instancji roboczej:
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(); } } }
W usłudze SleepWorkerTest te dane wejściowe można przesłać do
TestWorkerBuilder, aby zaspokoić potrzeby związane z: 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 = TestWorkerBuilder<SleepWorker>( 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())); } }
Więcej informacji na temat interfejsu API TestWorkerBuilder znajdziesz na stronie z dokumentacją
TestListenableWorkerBuilder,
nadklasa TestWorkerBuilder.
Testowanie usługi ListenableWorker i jej wariantów
Aby przetestować ListenableWorker lub
warianty (CoroutineWorker)
i RxWorker), należy użyć funkcji
TestListenableWorkerBuilder.
Główna różnica między obiektem TestWorkerBuilder a
TestListenableWorkerBuilder.
jest to, że TestWorkerBuilder pozwala określić tło Executor używane do
uruchomiono Worker, a TestListenableWorkerBuilder korzysta z
logikę podziału na wątki w implementacji ListenableWorker.
Załóżmy na przykład, że musimy przetestować obiekt CoroutineWorker, który wygląda tak:
class SleepWorker(context: Context, parameters: WorkerParameters) :
CoroutineWorker(context, parameters) {
override suspend fun doWork(): Result {
delay(1000L) // milliseconds
return Result.success()
}
}
Aby przetestować interfejs SleepWorker, najpierw tworzymy instancję instancji roboczej za pomocą
TestListenableWorkerBuilder, a następnie wywołaj jej funkcję doWork w argumencie
współpracą.
@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 sprawdzi się jako narzędzie do tworzenia współpracowników testów, dzięki czemu każdy kod
które byłyby wykonywane asynchronicznie, są uruchamiane równolegle.
Testowanie implementacji RxWorker jest podobne do testowania CoroutineWorker, ponieważ
TestListenableWorkerBuilder może obsługiwać dowolną podklasę klasy ListenableWorker.
Rozważ użycie wersji SleepWorker, która zamiast współprogramów używa RxJava.
Kotlin
class SleepWorker( context: Context, parameters: WorkerParameters ) : RxWorker(context, parameters) { override fun createWork(): Single<Result> { 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 Single<Result> createWork() { return Single.just(Result.success()) .delay(1000L, TimeUnit.MILLISECONDS); } }
Wersja SleepWorkerTest, w ramach której testujesz obiekt RxWorker, może wyglądać podobnie do tej
w wersji, w której przetestowano CoroutineWorker. Używasz tego samego
TestListenableWorkerBuilder, ale teraz dzwonisz pod numer createWork użytkownika RxWorker
. createWork zwraca wartość Single, której możesz użyć do zweryfikowania
zachowanie pracowników. TestListenableWorkerBuilder obsługuje wszystkie wątki
i równoległego wykonywania kodu instancji roboczej.
Kotlin
@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())) } } }
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()))); } }