Testowanie implementacji instancji roboczej

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

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

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