Testing Worker implementation

WorkManager provides APIs for testing Worker, ListenableWorker, and the ListenableWorker variants (CoroutineWorker and RxWorker).

Testing Workers

Let’s say we have a Worker which looks like this:

Kotlin

classSleepWorker(context:Context,parameters:WorkerParameters):
Worker(context,parameters){
overridefundoWork():Result{
// Sleep on a background thread.
Thread.sleep(1000)
returnResult.success()
}
}

Java

publicclass SleepWorkerextendsWorker{
publicSleepWorker(
@NonNullContextcontext,
@NonNullWorkerParametersworkerParameters){
super(context,workerParameters);
}
@NonNull
@Override
publicResultdoWork(){
try{
Thread.sleep(1000);
}catch(InterruptedExceptionignore){
returnResult.success();
}
}
}

To test this Worker, you can use TestWorkerBuilder. This builder helps build instances of Worker that can be used for the purpose of testing business logic.

Kotlin

// Kotlin code uses the TestWorkerBuilder extension to build
// the Worker
@RunWith(AndroidJUnit4::class)
classSleepWorkerTest{
privatelateinitvarcontext:Context
privatelateinitvarexecutor:Executor
@Before
funsetUp(){
context=ApplicationProvider.getApplicationContext()
executor=Executors.newSingleThreadExecutor()
}
@Test
funtestSleepWorker(){
valworker=TestWorkerBuilder<SleepWorker>(
context=context,
executor=executor
).build()
valresult=worker.doWork()
assertThat(result,`is`(Result.success()))
}
}

Java

@RunWith(AndroidJUnit4.class)
publicclass SleepWorkerJavaTest{
privateContextcontext;
privateExecutorexecutor;
@Before
publicvoidsetUp(){
context=ApplicationProvider.getApplicationContext();
executor=Executors.newSingleThreadExecutor();
}
@Test
publicvoidtestSleepWorker(){
SleepWorkerworker=
(SleepWorker)TestWorkerBuilder.from(context,
SleepWorker.class,
executor)
.build();
Resultresult=worker.doWork();
assertThat(result,is(Result.success()));
}
}

TestWorkerBuilder can also be used to set tags, such as inputData or runAttemptCount, so that you can verify worker state in isolation. Consider an example in which SleepWorker takes in a sleep duration as input data rather than it being a constant defined in the worker:

Kotlin

classSleepWorker(context:Context,parameters:WorkerParameters):
Worker(context,parameters){
overridefundoWork():Result{
// Sleep on a background thread.
valsleepDuration=inputData.getLong(SLEEP_DURATION,1000)
Thread.sleep(sleepDuration)
returnResult.success()
}
companionobject{
constvalSLEEP_DURATION="SLEEP_DURATION"
}
}

Java

publicclass SleepWorkerextendsWorker{
publicstaticfinalStringSLEEP_DURATION="SLEEP_DURATION";
publicSleepWorker(
@NonNullContextcontext,
@NonNullWorkerParametersworkerParameters){
super(context,workerParameters);
}
@NonNull
@Override
publicResultdoWork(){
try{
longduration=getInputData().getLong(SLEEP_DURATION,1000);
Thread.sleep(duration);
}catch(InterruptedExceptionignore){
returnResult.success();
}
}
}

In SleepWorkerTest, you can provide that input data to your TestWorkerBuilder to satisfy the needs of SleepWorker.

Kotlin

// Kotlin code uses the TestWorkerBuilder extension to build
// the Worker
@RunWith(AndroidJUnit4::class)
classSleepWorkerTest{
privatelateinitvarcontext:Context
privatelateinitvarexecutor:Executor
@Before
funsetUp(){
context=ApplicationProvider.getApplicationContext()
executor=Executors.newSingleThreadExecutor()
}
@Test
funtestSleepWorker(){
valworker=TestWorkerBuilder<SleepWorker>(
context=context,
executor=executor,
inputData=workDataOf("SLEEP_DURATION"to1000L)
).build()
valresult=worker.doWork()
assertThat(result,`is`(Result.success()))
}
}

Java

@RunWith(AndroidJUnit4.class)
publicclass SleepWorkerJavaTest{
privateContextcontext;
privateExecutorexecutor;
@Before
publicvoidsetUp(){
context=ApplicationProvider.getApplicationContext();
executor=Executors.newSingleThreadExecutor();
}
@Test
publicvoidtestSleepWorker(){
DatainputData=newData.Builder()
.putLong("SLEEP_DURATION",1000L)
.build();
SleepWorkerworker=
(SleepWorker)TestWorkerBuilder.from(context,
SleepWorker.class,executor)
.setInputData(inputData)
.build();
Resultresult=worker.doWork();
assertThat(result,is(Result.success()));
}
}

For more details on the TestWorkerBuilder API, see the reference page for TestListenableWorkerBuilder, the superclass of TestWorkerBuilder.

Testing ListenableWorker and its variants

To test a ListenableWorker or its variants (CoroutineWorker and RxWorker), use TestListenableWorkerBuilder. The main difference between TestWorkerBuilder and a TestListenableWorkerBuilder is that TestWorkerBuilder lets you specify the background Executor used to run the Worker, whereas TestListenableWorkerBuilder relies on the threading logic of the ListenableWorker implementation.

For example, suppose we need to test a CoroutineWorker which looks like this:

classSleepWorker(context:Context,parameters:WorkerParameters):
CoroutineWorker(context,parameters){
overridesuspendfundoWork():Result{
delay(1000L)// milliseconds
returnResult.success()
}
}

To test SleepWorker, we first create an instance of the Worker using TestListenableWorkerBuilder and then call its doWork function within a coroutine.

@RunWith(AndroidJUnit4::class)
classSleepWorkerTest{
privatelateinitvarcontext:Context
@Before
funsetUp(){
context=ApplicationProvider.getApplicationContext()
}
@Test
funtestSleepWorker(){
valworker=TestListenableWorkerBuilder<SleepWorker>(context).build()
runBlocking{
valresult=worker.doWork()
assertThat(result,`is`(Result.success()))
}
}
}

runBlocking makes sense as a coroutine builder for your tests so that any code that would execute asynchronously is instead run in parallel.

Testing an RxWorker implementation is similar to testing CoroutineWorker, as TestListenableWorkerBuilder can handle any subclass of ListenableWorker. Consider a version of SleepWorker that uses RxJava instead of coroutines.

Kotlin

classSleepWorker(
context:Context,
parameters:WorkerParameters
):RxWorker(context,parameters){
overridefuncreateWork():Single<Result>{
returnSingle.just(Result.success())
.delay(1000L,TimeUnit.MILLISECONDS)
}
}

Java

publicclass SleepWorkerextendsRxWorker{
publicSleepWorker(@NonNullContextappContext,
@NonNullWorkerParametersworkerParams){
super(appContext,workerParams);
}
@NonNull
@Override
publicSingle<Result>createWork(){
returnSingle.just(Result.success())
.delay(1000L,TimeUnit.MILLISECONDS);
}
}

A version of SleepWorkerTest that tests an RxWorker may look similar to the version that tested a CoroutineWorker. You use the same TestListenableWorkerBuilder but now call into RxWorker’s createWork function. createWork returns a Single that you can use to verify the behavior of your worker. TestListenableWorkerBuilder handles any threading complexities and executes your worker code in parallel.

Kotlin

@RunWith(AndroidJUnit4::class)
classSleepWorkerTest{
privatelateinitvarcontext:Context
@Before
funsetUp(){
context=ApplicationProvider.getApplicationContext()
}
@Test
funtestSleepWorker(){
valworker=TestListenableWorkerBuilder<SleepWorker>(context).build()
worker.createWork().subscribe{result->
assertThat(result,`is`(Result.success()))
}
}
}

Java

@RunWith(AndroidJUnit4.class)
publicclass SleepWorkerTest{
privateContextcontext;
@Before
publicvoidsetUp(){
context=ApplicationProvider.getApplicationContext();
}
@Test
publicvoidtestSleepWorker(){
SleepWorkerworker=TestListenableWorkerBuilder.from(context,SleepWorker.class)
.build();
worker.createWork().subscribe(result->
assertThat(result,is(Result.success())));
}
}

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2026年02月26日 UTC.