0

I am developing an Android application using Kotlin. I am writing instrumented tests for my code. Now I am struggling to write an instrumented test for a particular functionality. Following is the scenario I want to write test for.

I have three activities, LoginActivity, RegisterActivity and HomeActivity. LoginActivity starts the RegisterActivity using the startActivityForResult method. Then within the RegisterActivity, after registration, it finishes the activity using finishActivity method. So the onActivityResult callback of the LoginActivity class is called. Within the onActivityResult, it starts the HomeActivity using the startActivity method.

So, how can I test that if the HomeActivity is started within the onActivityResult callback of the LoginActivity when the registration is completed within the RegisterActivity?

This is my current incomplete code in an attempt to test that particular functionality

@RunWith(AndroidJUnit4::class)
class RegisterFormTest
{
    @Rule @JvmField
    val registerActivityRule: ActivityTestRule<RegisterActivity> = ActivityTestRule<RegisterActivity>(RegisterActivity::class.java)

    @Before
    fun setUp() {
    }

    @Test fun registerFormStartsHomeActivityAfterLogin() {
        Intents.init()
        FakeAuthService.SCENARIO_UNDER_TEST = FakeAuthService.SCENARIO_REGISTER_SUCCESSFUL

        onView(withId(R.id.register_button_submit)).perform(click())

        val accessToken = (registerActivityRule.activity.application as MockApplicationController).getLocalStorage()?.getString(ApplicationController.PREF_KEY_ACCESS_TOKEN, "")
        Assert.assertEquals(FakeAuthService.FAKE_ACCESS_TOKEN, accessToken)

        Thread.sleep(1000)


    Intents.intended(IntentMatchers.hasComponent(HomeActivity::class.java.name))

    Intents.release()

    }
}

But the test above does not work. It fails. How can I correctly test my scenario?

This is how I finish the activity in the RegisterActivity class

setResult(Activity.RESULT_OK)
finish()

This is the onActivityResult callback within in LoginActivity class

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode == RegisterActivity.ACTIVITY_CODE && resultCode == Activity.RESULT_OK) {
            startHomeActivity()
        }
    }

This is the error

2019-10-21 14:51:08.642 25433-25461/com.example.memento E/TestRunner: ----- begin exception ----- 2019-10-21 14:51:08.642 25433-25461/com.example.memento E/TestRunner: junit.framework.AssertionFailedError: Wanted to match 1 intents. Actually matched 0 intents.

IntentMatcher: has component: has component with: class name: is "com.example.myapp.HomeActivity" package name: an instance of java.lang.String short class name: an instance of java.lang.String

Matched intents:[]

Recorded intents:[]
    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)

Everything is working as expected when I test it manually using the actual device.

Wai Yan Hein
  • 13,651
  • 35
  • 180
  • 372

1 Answers1

0

Consider setting a result in the RegisterActivity passing a flag in the Intent and passing the Intent in setResult(OK,Intent). That Intent would contain the flag indicating that registration was completed.

In onActivityResult() of LoginActivity, extract the flag(boolean) from the Intent you passed in RegisterActivityand pass that flag in the Intent used to start the HomeActivity. Check the Intent in onCreate() of HomeActivity and verify that the flag was passed indicating registration was completed .

If the flag is received, set the value of a TextView to some random string of your choosing indicating, and then check that the text of that TextView matches your random string using espresso matchers.

Jarvis
  • 392
  • 1
  • 6