Android NDK开发详解后台任务之测试 Worker 实现
WorkManager 提供了用于测试 Worker、ListenableWorker 和 ListenableWorker 变体(CoroutineWorker 和 RxWorker)的 API。
测试 worker
假设我们有一个类似以下示例的 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 = 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 也可用于设置标记(例如 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 = 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()));
}
}
如需详细了解 TestWorkerBuilder API,请参阅 TestListenableWorkerBuilder(TestWorkerBuilder 的父类)的参考页面。
测试 ListenableWorker 及其变体
如需测试 ListenableWorker 或其变体(CoroutineWorker 和 RxWorker),请使用 TestListenableWorkerBuilder。TestWorkerBuilder 和 TestListenableWorkerBuilder 的主要区别在于,TestWorkerBuilder 允许指定用来运行 Worker 的后台 Executor,而 TestListenableWorkerBuilder 依赖 ListenableWorker 实现的线程逻辑。
例如,假设我们需要测试类似以下示例的 CoroutineWorker:
class SleepWorker(context: Context, parameters: WorkerParameters) :
CoroutineWorker(context, parameters) {
override suspend fun doWork(): Result {
delay(1000L) // milliseconds
return Result.success()
}
}
为了测试 SleepWorker,我们首先使用 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(): 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);
}
}
测试 RxWorker 的 SleepWorkerTest 版本可能类似于测试 CoroutineWorker 的版本。您使用相同的 TestListenableWorkerBuilder,但现在会调用 RxWorker 的 createWork 函数。createWork 会返回一个 Single,可用于验证工作器的行为。TestListenableWorkerBuilder 可处理线程方面的任何复杂问题,还能并行执行工作器代码。
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())));
}
}
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2023-11-03。