如何对WorkManager的Worker进行单元测试

11

如何对 WorkManager Worker 进行单元测试?

这里是一个示例 Worker:

public class SampleWorker extends Worker {

    private static final String TAG = "SampleWorker";
    private static final String WORKER_TAG = "SAMPLE";

    static final String KEY_DATA_1 = "KEY_DATA_1";
    static final String KEY_DATA_2 = "KEY_DATA_2";


    public SampleWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    public static WorkRequest createWorkRequest(String data1, String data2) {
        Constraints constraints = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .build();

        Data inputData = createData(data1, data2);

        return new OneTimeWorkRequest.Builder(SampleWorker.class)
                .setConstraints(constraints)
                .setInputData(inputData)
                .addTag(WORKER_TAG)
                .build();
    }

    static Data createData(String data1, String data2) {
        return new Data.Builder()
                .putString(KEY_DATA_1, data1)
                .putString(KEY_DATA_2, data2)
                .build();
    }

    @NonNull
    @Override
    public Result doWork() {
        try {
            Data inputData = getInputData();
            businessLogicHere(inputData.getString(KEY_DATA_1), inputData.getString(KEY_DATA_2));

            return Result.SUCCESS;
        } catch (Exception e) {
            Log.e(TAG, "doWork failed", e);
            return Result.FAILURE;
        }
    }

    private void businessLogicHere(String data1, String data2) {
        // no-op
    }
}

你可以查看 androidx.work.testing 库。从 2.1 版本开始,你可以创建一个 TestWorkerBuilder<SampleWorker> 或者 TestListenableWorkerBuilder<SampleWorker>(如果你正在使用 CoroutineWorker/RxWorkers)。然后你可以传递构造函数参数,例如 runAttemptCountinputData 等,并调用 startWork() 来启动你的 worker 的 doWork() 方法。 这里的示例应该有助于澄清问题:https://codelabs.developers.google.com/codelabs/kotlin-coroutines/#11 - dgelormini
2个回答

5

在 Work Manager alpha10 版本中,添加了一个带有 WorkerParameters 的构造函数,因此更容易传递输入的 Data

注意:我在 Worker 类中创建了工厂方法,因此更容易阅读传递和使用 Worker 中的输入数据。

下面是样例单元测试:

  @RunWith(PowerMockRunner.class)
    @PrepareForTest({WorkerParameters.class})
    public class SampleWorkerTest {

    @Mock
    Context context;

    WorkerParameters workerParams;

    Data inputData;

    SampleWorker worker;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        workerParams = PowerMockito.mock(WorkerParameters.class);

        inputData = SampleWorker.createData("data one", "data two");
        when(workerParams.getInputData()).thenReturn(inputData);

        worker = new SampleWorker(context, workerParams);
    }

    @Test
    public void testCreateWorkRequestFactoryMethod() {
        WorkRequest workRequest = SampleWorker.createWorkRequest("data one", "data two");
        WorkSpec workSpec = workRequest.getWorkSpec();

        // verify constraints
        assertThat(workSpec.constraints.getRequiredNetworkType(), is(equalTo(NetworkType.CONNECTED)));

        // verify input data
        assertThat(workSpec.input.getString(SampleWorker.KEY_DATA_1), is(equalTo("data one")));
        assertThat(workSpec.input.getString(SampleWorker.KEY_DATA_2), is(equalTo("data two")));
    }

    @Test
    public void testDoWorkSuccess() {
        Worker.Result result = worker.doWork();

        // verify business logic here

        assertThat(result, is(equalTo(Worker.Result.SUCCESS)));
    }
}

1
无法在1.0.0-rc01上工作,因为workerparams现在是final的。您无法模拟final类。 - Claire
2
目前我正在使用PowerMockito,我相信最新的Mockito允许模拟final类。我将使用PowerMockito更新答案。 - Prakash

1

这里有一个 WorkManager 测试库。添加依赖项:

androidTestImplementation "androidx.work:work-testing:$work_version"

这是一个简单的例子:

fun downloadFile() {
    val context = InstrumentationRegistry.getInstrumentation().targetContext
    val inputData = workDataOf("key" to "myValue")

    val worker = TestListenableWorkerBuilder<DownloadFileWorker>(context)
        .setInputData(inputData)
        .build()
    val result = worker.doWork()

    assertThat(result, Is(isEqualTo(ListenableWorker.Result.success())))
}

您可以根据需要使用 TestListenableWorkerBuilder 进一步配置模拟。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接