代码之家  ›  专栏  ›  技术社区  ›  Wai Yan Hein

Android单元测试一个活动是否以超时或延迟后开始是不起作用的

  •  0
  • Wai Yan Hein  · 技术社区  · 6 年前

    这是我的活动课

    class MainActivity : AppCompatActivity() {
    
        companion object {
            val LAUNCH_DELAY: Long = 2000
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            Handler().postDelayed({
                this.startLoginActivity()
            }, LAUNCH_DELAY)
        }
    
        protected fun startLoginActivity()
        {
            startActivity(Intent(this, LoginActivity::class.java))
        }
    }
    

    我试过了

    @RunWith(AndroidJUnit4::class)
    class MainActivityTest {
        @Rule @JvmField
        val mainActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule<MainActivity>(MainActivity::class.java)
    
        @Test
        fun itStartsLoginActivityAfterDelay() {
            Intents.init()
            mainActivityRule.launchActivity(Intent())
            Handler().postDelayed({
                Intents.intended(hasComponent(LoginActivity::class.java.name))
                Intents.release()
            }, 2000);
        }
    }
    

    我犯了这个错误

    E/TestRunner: failed: itStartsLoginActivityAfterDelay(com.example.memento.MainActivityTest)
        ----- begin exception -----
    E/TestRunner: java.lang.RuntimeException: Can't create handler inside thread Thread[Instr: com.example.memento.MockTestRunner,5,main] that has not called Looper.prepare()
            at android.os.Handler.<init>(Handler.java:205)
            at android.os.Handler.<init>(Handler.java:118)
            at com.example.memento.MainActivityTest.itStartsLoginActivityAfterDelay(MainActivityTest.kt:37)
            at java.lang.reflect.Method.invoke(Native Method)
            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 androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:531)
            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 androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:104)
            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 androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
            at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
            at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
        ----- end exception -----
    

    我也试过这个

    @Test
        fun itStartsLoginActivityAfterDelay() {
            Intents.init()
            mainActivityRule.launchActivity(Intent())
            Thread.sleep(2000);
            Intents.intended(hasComponent(LoginActivity::class.java.name))
            Intents.release()
        }
    

    这次我犯了这个错误

    E/TestRunner: failed: itStartsLoginActivityAfterDelay(com.example.memento.MainActivityTest)
    E/TestRunner: ----- begin exception -----
    E/TestRunner: androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: Wanted to match 1 intents. Actually matched 2 intents.
    
        IntentMatcher: has component: has component with: class name: is "com.example.memento.LoginActivity" package name: an instance of java.lang.String short class name: an instance of java.lang.String
    
        Matched intents:
        -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
        -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
    
        Recorded intents:
        -Intent { flg=0x10000000 cmp=com.example.memento/.MainActivity } handling packages:[[com.example.memento]])
        -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
        -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
            at dalvik.system.VMStack.getThreadStackTrace(Native Method)
            at java.lang.Thread.getStackTrace(Thread.java:1538)
            at androidx.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:94)
            at androidx.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:57)
            at androidx.test.espresso.ViewInteraction.waitForAndHandleInteractionResults(ViewInteraction.java:318)
            at androidx.test.espresso.ViewInteraction.check(ViewInteraction.java:300)
            at androidx.test.espresso.intent.Intents.intended(Intents.java:189)
            at androidx.test.espresso.intent.Intents.intended(Intents.java:170)
            at com.example.memento.MainActivityTest.itStartsLoginActivityAfterDelay(MainActivityTest.kt:47)
            at java.lang.reflect.Method.invoke(Native Method)
            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 androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
            at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:531)
            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 androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:104)
            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 androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
            at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
            at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
         Caused by: junit.framework.AssertionFailedError: Wanted to match 1 intents. Actually matched 2 intents.
    
        IntentMatcher: has component: has component with: class name: is "com.example.memento.LoginActivity" package name: an instance of java.lang.String short class nam
        ----- end exception -----
    I/TestRunner: finished: itStartsLoginActivityAfterDelay(com.example.memento.MainActivityTest)
    I/MonitoringInstr: Activities that are still in CREATED to STOPPED: 4
        Finishing activity: com.example.memento.LoginActivity@97c0733
    I/MonitoringInstr: Finishing activity: com.example.memento.LoginActivity@65a941b
    I/MonitoringInstr: Finishing activity: com.example.memento.MainActivity@39cc00e
    
    androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: Wanted to match 1 intents. Actually matched 2 intents.
    
    IntentMatcher: has component: has component with: class name: is "com.example.memento.LoginActivity" package name: an instance of java.lang.String short class name: an instance of java.lang.String
    
    Matched intents:
    -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
    -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
    
    Recorded intents:
    -Intent { flg=0x10000000 cmp=com.example.memento/.MainActivity } handling packages:[[com.example.memento]])
    -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
    -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
    at dalvik.system.VMStack.getThreadStackTrace(Native Method)
    at java.lang.Thread.getStackTrace(Thread.java:1538)
    at androidx.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:94)
    at androidx.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:57)
    at androidx.test.espresso.ViewInteraction.waitForAndHandleInteractionResults(ViewInteraction.java:318)
    at androidx.test.espresso.ViewInteraction.check(ViewInteraction.java:300)
    at androidx.test.espresso.intent.Intents.intended(Intents.java:189)
    at androidx.test.espresso.intent.Intents.intended(Intents.java:170)
    at com.example.memento.MainActivityTest.itStartsLoginActivityAfterDelay(MainActivityTest.kt:47)
    at java.lang.reflect.Method.invoke(Native Method)
    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 androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
    at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:531)
    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 androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:104)
    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 androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
    at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
    Caused by: junit.framework.AssertionFailedError: Wanted to match 1 intents. Actually matched 2 intents.
    
    IntentMatcher: has component: has component with: class name: is "com.example.memento.LoginActivity" package name: an instance of java.lang.String short class name: an instance of java.lang.String
    
    Matched intents:
    -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
    -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
    
    Recorded intents:
    -Intent { flg=0x10000000 cmp=com.example.memento/.MainActivity } handling packages:[[com.example.memento]])
    -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
    -Intent { cmp=com.example.memento/.LoginActivity } handling packages:[[com.example.memento]])
    at junit.framework.Assert.fail(Assert.java:50)
    at androidx.test.espresso.intent.VerificationModes$Times.verify(VerificationModes.java:80)
    at androidx.test.espresso.intent.Intents.internalIntended(Intents.java:346)
    at androidx.test.espresso.intent.Intents$2.check(Intents.java:193)
    at androidx.test.espresso.ViewInteraction$SingleExecutionViewAssertion.check(ViewInteraction.java:419)
    at androidx.test.espresso.ViewInteraction$2.call(ViewInteraction.java:282)
    at androidx.test.espresso.ViewInteraction$2.call(ViewInteraction.java:268)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
    

    0 回复  |  直到 6 年前
        1
  •  1
  •   adrianbukros    6 年前

    问题是目标意图有多个匹配项: Wanted to match 1 intents. Actually matched 2 intents

    intended(hasComponent(LoginActivity::class.java.name), Intents.times(2))
    
    

    更新:

    实际问题在你的测试中。

    你打电话来 mainActivityRule.launchActivity(Intent()) 在你的测试方法中,那一行开始另一行 MainAcivity LoginActivity 对于您(这就是为什么您的intent堆栈中有两个)。

    mainActivityRule: ActivityTestRule<MainActivity> 您在类中定义的每个测试方法都是这样做的。

    这应该起作用:

    @Test
    fun itStartsLoginActivityAfterDelay() {
            Intents.init()
            Thread.sleep(2000);
            Intents.intended(hasComponent(LoginActivity::class.java.name))
            Intents.release()
    }