Robolectric测试需要等待的东西在一个线程 [英] Robolectric test needs to wait for something on a thread
问题描述
我的类做这样的:
public void doThing() {
Doer doer = new Doer();
Thread thread = new Thread(doer);
thread.start();
}
在'实干家'类是一个内部类:
The 'Doer' class is an inner class:
private class Doer implements Runnable {
public void run() {
Intent myIntent = new Intent(mContext, MyService.class);
mContext.startService(myIntent);
...Some more stuff...
}
这工作得很好。
我需要测试这一点使用Robolectric。当然 doThing()
立即返回,我需要给线程有机会运行之前我
I need to test this using Robolectric. Naturally doThing()
returns immediately and I need to give the thread a chance to run before I do
ShadowApplication.getInstance().getNextStartedService()
我怎么能等待线程运行?
How can I wait for the thread to run?
我曾尝试:
Robolectric.flushForegroundThreadScheduler();
Robolectric.flushBackgroundThreadScheduler();
和他们都没有达到预期效果:他们我的意图之前都返回已发送
and neither has the desired effect: they both return before my Intent has been sent.
目前我已经通过把睡眠到我的测试周围工作的时刻:
At the moment I have worked around it by putting a sleep into my test:
Thread.sleep(10);
和它的伎俩,但它显然是可怕的 - 这是等着使我悲痛的竞争条件
and it does the trick, but it's clearly horrible - it's a race condition waiting to cause me grief.
推荐答案
下面是一个工作的例子。
Here is a working example.
请注意,它依赖于一个电话告诉Robolectric使现场HTTP查询:
Note that it relies on a call to tell Robolectric to enable live HTTP queries:
FakeHttp.getFakeHttpLayer().interceptHttpRequests(false);
在code一ConditionVariable管理后台任务的完成跟踪。
The code a ConditionVariable to manage tracking of completion of the background task.
我不得不加入到我的项目的的build.gradle文件(在依赖块):
I had to add this to my project's build.gradle file (in the dependencies block):
// http://robolectric.org/using-add-on-modules/
compile 'org.robolectric:shadows-httpclient:3.0'
testCompile 'org.robolectric:shadows-httpclient:3.0'
我希望这有助于!
I hope this helps!
皮特
// This is a dummy class that makes a deferred HTTP call.
static class ItemUnderTest {
interface IMyCallbackHandler {
void completedWithResult(String result);
}
public void methodUnderTestThatMakesDeferredHttpCall(final IMyCallbackHandler completion) {
// Make the deferred HTTP call in here.
// Write the code such that completion.completedWithResult(...) is called once the
// Http query has completed in a separate thread.
// This is just a dummy/example of how things work!
new Thread() {
@Override
public void run() {
// Thread entry point.
// Pretend our background call was handled in some way.
completion.completedWithResult("Hello");
}
}.start();
}
}
@org.junit.Test
public void testGetDetailedLatestResultsForWithInvalidEmailPasswordUnit_LiveQuery() throws Exception {
// Tell Robolectric that we want to perform a "Live" test, against the real underlying server.
FakeHttp.getFakeHttpLayer().interceptHttpRequests(false);
// Construct a ConditionVariable that is used to signal to the main test thread,
// once the background work has completed.
final ConditionVariable cv = new ConditionVariable();
// Used to track that the background call really happened.
final boolean[] responseCalled = {false};
final ItemUnderTest itemUnderTest = new ItemUnderTest();
// Construct, and run, a thread to perform the background call that we want to "wait" for.
new Thread() {
@Override
public void run() {
// Thread entry point.
// Make the call that does something in the background...!
itemUnderTest.methodUnderTestThatMakesDeferredHttpCall(
new ItemUnderTest.IMyCallbackHandler() {
@Override
public void completedWithResult(String result) {
// This is intended to be called at some point down the line, outside of the main thread.
responseCalled[0] = true;
// Verify the result is what you expect, in some way!
org.junit.Assert.assertNotNull(result);
// Unblock the ConditionVariable... so the main thread can complete
cv.open();
}
}
);
// Nothing to do here, in particular...
}
}.start();
// Perform a timed-out wait for the background work to complete.
cv.block(5000);
org.junit.Assert.assertTrue(responseCalled[0]);
}
这篇关于Robolectric测试需要等待的东西在一个线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!