【问题标题】:How to test a Firebase task on Android?如何在 Android 上测试 Firebase 任务?
【发布时间】:2016-11-17 14:05:47
【问题描述】:

现在我正在尝试使用 JUnit4 对其进行测试,但我得到了

java.lang.IllegalStateException:
    Must not be called on the main application thread

at com.google.android.gms.common.internal.zzab.zzhj(Unknown Source)
at com.google.android.gms.common.internal.zzab.zzate(Unknown Source)
at com.google.android.gms.tasks.Tasks.await(Unknown Source)
at com.example.tasks.GetUserProfileTest.then(GetUserProfileTest.java:18)
    <27 internal calls>

Process finished with exit code 255

我创建了一个Continuation 任务,它对Firebase Realtime Database 执行操作。

public class GetUserProfile implements Continuation<String, Task<Profile>>,
        ValueEventListener {

    private TaskCompletionSource<Profile> mTaskCompletionSource;
    private DatabaseReference mDatabase;

    public GetUserProfile() {
        mTaskCompletionSource = new TaskCompletionSource();
        mDatabase = FirebaseDatabase.getInstance().getReference();
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        mDatabase.removeEventListener(this);
        mTaskCompletionSource.setException(databaseError.toException());
    }

    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        mDatabase.removeEventListener(this);
        mTaskCompletionSource.setResult(dataSnapshot.getValue(Profile.class));
    }

    @Override
    public Task<Profile> then(Task<String> task) {
        mDatabase.child(task.getResult()).addValueEventListener(this);
        return mTaskCompletionSource.getTask();
    }
}

并对其进行单元测试:

public class GetUserProfileTest {
    @Test
    public void then() throws Exception {
        Task<Profile> task = Tasks.<String>forResult("17354686546")
            .continueWithTask(new GetUserProfile());

        try {
            Profile profile = Tasks.await(task);
            assertEquals(profile.getEmail(), "john.connor@email.com");
        } catch (ExecutionException e) {
            fail(e.getMessage());
        } catch (InterruptedException e) {
            fail(e.getMessage());
        }
    }
}

有没有不使用handlers 或CountDownLatch 的简单方法来测试任务?

【问题讨论】:

  • 究竟是哪一行导致了错误,它的完整堆栈跟踪是什么?
  • Tasks.await 因为它阻塞了主线程。我知道可以使用CountDownLatch 来完成,但我希望找到更优雅的解决方案。
  • 我会直接在 Continuation 上调用 then 方法。此外,作为一个真正的单元测试,我会完全模拟数据库并检查它是否被正确查阅。但是如果单元测试真的必须测试线程(最好不要),CDL 是要走的路。
  • @DougStevenson,视图和演示者测试使用模拟数据,但测试与 Firebase 的通信也是项目要求之一。对于tcs.setResult 和tcs.setException,直接调用then 效果很好

标签: android asynchronous firebase junit mockito


【解决方案1】:
public class GetUserProfileTest {
    @Test
    public void then() throws Exception {
        try {
            Task<String> previousTask = Tasks.forResult("17354686546");
            GetUserProfile continuation = new GetUserProfile();
            Profile profile = continuation
                    .then(previousTask)
                    .getResult();

            assertEquals(profile.getEmail(), "john.connor@email.com");
        } catch (ExecutionException e) {
            fail(e.getMessage());
        } catch (InterruptedException e) {
            fail(e.getMessage());
        }
    }
}

【讨论】:

  • 上述测试方案抛出java.lang.IllegalStateException: Task is not yet complete
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-14
  • 1970-01-01
相关资源
最近更新 更多