Reputation: 133
I am in process of migration to robolectric 3.0
Problem Statement--
I have a class AppUtility, which is instantiated inside MyActivity, so to check its methods are invoked, I need to mock it inside my test before setting up the MyActivity.
Here is my code:
@Mock
private AppUtility mockAppUtility;
@Before
public void setUp() {
initMocks(this);
myActivity= Robolectric.setupActivity(MyActivity.class);
equalsButton = (Button) myActivity.findViewById(R.id.equals_sign);
shadowActivity = Shadows.shadowOf(myActivity);
}
Here is the test method:--
@Test
public void shouldCallStartAlarm() {
for (int i = 0; i < 4; i++) {
equalsButton.performClick();
}
verify(mockAppUtility).startAlarm();
}
Bu I get the following error msg:-- which show mock is not linked to the activity, how can I bind it to activity??
Actually, there were zero interactions with this mock.
But the mock object is not associated with the test. With earlier version of Robolectric I use to associate the mock object on activity creation, by overriding it as below
myActivity = new MyActivity() {
@Override
AppUtility getUtil() {
return mockAppUtility;
}
};
myActivity.onCreate(new Bundle());
and it use to work fine, with Robolectric 3.0 , how can I bind the mock object before starting the activity.
Following @nenick your second option:This is how it looks
@Mock
private AppUtility appUtility;
@InjectMocks
private MyActivity myActivity;
@Before
public void setUp() {
ActivityController<MyActivity> activityController = Robolectric.buildActivity(MyActivity.class);
// myActivity= Robolectric.setupActivity(MyActivity.class);
myActivity=activityController.get();
initMocks(this);
activityController.setup();
equalsButton = (Button) myActivity.findViewById(R.id.equals_sign);
// shadowActivity = Shadows.shadowOf(calculatorActivity);
}
but I get fllowing exception:-
java.lang.IllegalArgumentException: attempted to invoke public final android.app.Application org.robolectric.shadows.ShadowActivity.getApplication() on instance of class org.com.android.AppUtility$$EnhancerByMockitoWithCGLIB$$77c74666, but AppUtility$$EnhancerByMockitoWithCGLIB$$77c74666 doesn't extend ShadowActivity
it breaks at step--activityController.setup();
Upvotes: 2
Views: 5085
Reputation: 7438
Just set mock is easy with mockito mock injection feature.
@Mock
private AppUtility mockAppUtility;
@InjectMocks
Activity mActivity;
@Before
public void setUp() {
myActivity= Robolectric.setupActivity(MyActivity.class);
equalsButton = (Button) myActivity.findViewById(R.id.equals_sign);
shadowActivity = Shadows.shadowOf(myActivity);
// create and injects mocks into object annotated with @InjectMocks
initMocks(this);
}
To set mocks before activity setup (onCreate, ...) is called you must access your activity before setup.
@Before
public void setUp() {
ActivityController<Activity> activityController = Robolectric.buildActivity(Activity.class);
// get the activity instance
mActivity = activityController.get()
initMocks(this);
// now setup your activity after mock injection
activityController.setup()
}
Upvotes: 4
Reputation: 20130
One of the main rule of unit testing - never mock class under the test. You might spy
on it but again it is rescue challenge which you should not use in this case.
Another smell
showing that you have wake test - when you will be able to run this tests successfully it will not guarantee that real alarm set. It will guarantee only that this method was called. So it is better to verify set alrams instead of verifying method call. Check this link for the example use of shadow alarm manager
Upvotes: 0