Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to start unbound service inside of Android JUnit 4 instrumented test

I'm trying to test basic unbound service with testing support library framework: http://developer.android.com/tools/testing-support-library/index.html

LocalService.java:

public class LocalService extends Service {
@Override
public IBinder onBind(Intent intent) {
        return null;
    }
}

LocalServiceTest.java:

@RunWith(AndroidJUnit4.class)
public class LocalServiceTest {
    @Rule
    public final ServiceTestRule mServiceRule = new ServiceTestRule();

    @Test
    public void testWithUnboundService() throws TimeoutException {
        Intent serviceIntent =
            new Intent(InstrumentationRegistry.getTargetContext(), LocalService.class);

        mServiceRule.startService(serviceIntent);
    }
}

When I try to run test, I get following TimeoutException:

java.util.concurrent.TimeoutException: Waited for 5 SECONDS, but service was never connected
at android.support.test.rule.ServiceTestRule.waitOnLatch(ServiceTestRule.java:258)
at android.support.test.rule.ServiceTestRule.bindServiceAndWait(ServiceTestRule.java:207)
at android.support.test.rule.ServiceTestRule.startService(ServiceTestRule.java:137)
at com.example.android.testing.ServiceTestRuleSample.LocalServiceTest.testWithBoundService(LocalServiceTest.java:71)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at android.support.test.rule.ServiceTestRule$ServiceStatement.evaluate(ServiceTestRule.java:329)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:54)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:240)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1729)

Is it possible to test such kind of services with ServiceTestRule? If no, is there another appropriate way to start and stop services using JUnit 4 test classes?

like image 652
Raman Budny Avatar asked Mar 05 '16 10:03

Raman Budny


2 Answers

I met the same issue as you. When I searched the reason in Android reference of ServiceTestRule, I found the reason is so simple.

Note: This method only supports services that allow clients to bind to them. In other words, if your service onBind(Intent) method returns null then a TimeoutException will be thrown.

Therefore I changed my onBind() method to return a non-null binder.

@Override
public IBinder onBind(Intent i) {
    return new LocalBinder();
}

in which LocalBinder is defined as

public class LocalBinder extends Binder {
    LocalService getService() {
        return LocalService.this;
    }
}

Then the TimeoutException went away!

I guess the reason of test failure is that your test runner cannot bind the service under test. Although the service is running since you have started it in your case, but test runner cannot detect if the service is running. It has to flag your test case as failed.

like image 145
Huiyang Shan Avatar answered Oct 19 '22 13:10

Huiyang Shan


Try this one

@Rule
public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(60L, TimeUnit.SECONDS);
like image 24
user3124864 Avatar answered Oct 19 '22 13:10

user3124864