无法在 Android JUnit 4 检测测试中启动未绑定服务

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

我正在尝试使用测试支持库框架来测试基本的未绑定服务: 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);
    }
}

当我尝试 运行 测试时,出现以下 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.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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=13=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=13=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.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)

是否可以使用 ServiceTestRule 测试此类服务? 如果不是,是否有另一种使用 JUnit 4 测试启动和停止服务的合适方法 类?

这对我有用

@Test(timeout=1000 * 60)
public void testWithStartedService(){
    try {
        mServiceRule.startService(
                new Intent(InstrumentationRegistry.getTargetContext(), UpdaterService.class));
    } catch (TimeoutException e) {
        e.printStackTrace();
    }
    //do something
}

试试这个

@Rule
public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(60L, TimeUnit.SECONDS);

我遇到了和你一样的问题。当我在ServiceTestRule的Android参考文献中查找原因时,我发现原因很简单。

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.

因此我将我的 onBind() 方法更改为 return 一个非空的活页夹。

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

其中LocalBinder定义为

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

然后 TimeoutException 消失了!

我猜测试失败的原因是你的测试运行器无法绑定被测服务。 虽然服务是 运行 因为你已经在你的案例中启动了它,但是测试运行器无法检测服务是否是 运行。 它必须标记你的测试用例失败了。