简体   繁体   中英

Espresso / Mockito verify that method was called

I have a simple test using an activityTestRule that should check whether a method of the activity under test was called:

@Test
public void callLiveLocation() {
    MapSettingsActivity spy = spy(activityRule.getActivity());
    doNothing().when(spy).setLiveLocation();
    onView(withId(R.id.btn_map_current_location)).perform(click());
    verify(spy).setLiveLocation();
}

The method setLiveLocation() is being called when I check in debug mode.
However, the console tells me:

Wanted but not invoked: mapSettingsActivity.setLiveLocation(); -> at com.android.dx.mockito.InvocationHandlerAdapter.invoke(InvocationHandlerAdapter.java:53) Actually, there were zero interactions with this mock.

How do I check if the method of the activity under test was called?
I use Android's databinding for the button click, which invokes a callback, which in turn calls a method on the activity under test.

Note:

The method is a simple method on the activity:

public void setLiveLocation() {
    super.startLocationListener();
}

Edit:

I noticed that creating the spy returns null for a yet unknown reason:

MapSettingsActivity spy = spy(activityRule.getActivity());

First of all this is not exact solution of your problem, but maybe it will help you.

So this is how I handled similar problem. In general: in order Mockito could detect method call on spy object, this method must be called on spied object (if you understand what I'm talking about, cause I don`t)). It is not true in your case. Your setLiveLocation called on real instance of activity, which is stored in ActivityTestRule.

My example: I need to verify that RecyclerView`s adpter updateDataSet() method is called exactly once. This is how I did it in Kotlin:

    val adapter = activityTestRule.activity
            .find<RecyclerView>(R.id.reviewsList)
            .adapter as FlexibleAdapter<ReviewItem>

    assertNotNull(adapter)

    val spy = spy(adapter)

    activityTestRule.activity
            .runOnUiThread {
                activityTestRule.activity
                        .find<RecyclerView>(R.id.reviewsList)
                        .adapter = spy
            }

    doNothing().`when`(spy).updateDataSet(ArgumentMatchers.any())

    onView(withId(R.id.swipeRefresh)).perform(ViewActions.swipeDown())

    verify(spy, times(1)).updateDataSet(MOCKED_REVIEWS_FROM_SERVER.map(::ReviewItem))

So basically I get adapter from Recycler and change it to my spy adapter. My test finished successfully only when I made this replacement. In your case ActivityTestRule holds instance of real activity, so you need somehow to replace it with spy object. I`m not sure how to do it, but I suppose there is chance to create subclass of this rule and to create spy of activity maybe in constructor. Then you will get spied object and use it to verify any calls.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM