Reputation: 1319
The activity being tested is for a simple board game. When the conditions necessary for the game to be over are met, after doing several things to display who won etc, the following code is run:
// Return to main menu after 5 seconds
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, 5000);
I have an instrumentation test which uses ActivityInstrumentationTestCase2
. I can manufacture it so that the test starts with the board one move away from the above code being called. But after doing that move how can I assert that finish()
was called?
I've tried duplicating this test using an ActivityUnitTestCase
which has the isFinishCalled()
method, but I haven't been able to make it work.
Upvotes: 2
Views: 2426
Reputation: 16000
I have 2 possible solution for this problem:
Rewrite the test as Unit test with Robolectric framework:
public class MainActivity extends AppCompatActivity {
........
public void finishGame() {
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, 5000);
}
}
Then the test will look like:
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk=21)
public class MainActivityTest {
@Test
public void testFinishing() throws InterruptedException {
MainActivity mainActivity = new MainActivity();
assertFalse(mainActivity.isFinishing());
mainActivity.finishGame();
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
assertTrue(mainActivity.isFinishing());
}
}
Avoid Handler
in unit tests only:
public class MainActivity extends AppCompatActivity {
........
public void finishGame(boolean postDelayed) {
if (postDelayed) {
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, 5000);
return;
}
finish();
}
}
Then the test will look like:
public class MainActivityTest extends ActivityTestCase {
public MainActivityTest() {
super();
setActivity(new MainActivity());
}
public void testFinishing() {
assertFalse(getActivity().isFinishing());
((MainActivity)getActivity()).finishGame(false);
assertTrue(getActivity().isFinishing());
}
}
And in production code you call this method like finishGame(true)
.
In my project, I'm sticking to the second option (in my case, I'm testing FragmentTransaction
's behavior, with also required delay for ensuring the view is properly constructed)
I hope, it helps
Upvotes: 2