代码之家  ›  专栏  ›  技术社区  ›  Raman Budny

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

  •  10
  • Raman Budny  · 技术社区  · 8 年前

    我正在尝试使用测试支持库框架测试基本的未绑定服务: http://developer.android.com/tools/testing-support-library/index.html

    本地服务.java:

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

    本地服务测试.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$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)
    

    有可能用ServiceTestRule测试此类服务吗? 如果没有,是否有其他合适的方法使用JUnit4测试类启动和停止服务?

    3 回复  |  直到 8 年前
        1
  •  9
  •   Huiyang Shan    6 年前

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

    注意:此方法仅支持允许客户端绑定到的服务 他们换句话说,如果您的服务onBind(Intent)方法返回 null,则将引发TimeoutException。

    因此,我更改了onBind()方法以返回非空绑定器。

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

    其中LocalBinder定义为

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

    然后TimeoutException消失了!

    我想测试失败的原因是您的测试运行程序无法绑定正在测试的服务。 尽管在您的案例中启动服务后,服务正在运行,但测试运行程序无法检测服务是否正在运行。 它必须将测试用例标记为失败。

        2
  •  2
  •   Saeed Entezari    4 年前

    试试这个

    @Rule
    public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(60L, TimeUnit.SECONDS);
    
        3
  •  1
  •   EnduroDave    8 年前

    这对我有用

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