Android robolectric – how to simulate and inject business classes when creating activity objects
My task is to write unit tests for existing Android activities, and I haven't written code that conforms to unit tests (tight coupling)
Scenario: I have a stroagemanager class, which is instantiated in myactivity oncreate method
@Override
protected void onCreate(Bundle savedInstanceState)
{
StorageManager storagemanager = GetStorageManager(); // return new object of stroage manager
super.onCreate(savedInstanceState);.....
...
}
In order to create an activity instance through robolectric, I need to simulate myactivity before setting it in the test
Question: how to simulate and inject a myactivity object when it is created through robolectric
Note: This is an existing activity. I don't have much freedom to modify the activity code for large-scale expansion. In addition, we are using the mockito framework for simulation, so it would be great if you use mockito for examples
This is the sample code I tried to use robolectric in mockito, but it didn't work properly:
@RunWith(RobolectricTestRunner.class)
public class myActivityTest {
@Mock
private StorageManager storageManager;
@InjectMocks
MyActivity myActivity;
@Before
public void setUp() {
ActivityController<MyActivity> activityController = Robolectric.buildActivity(MyActivity.class);
myActivity = activityController.get();
// when(registrationActivity.GetMetricManager()).thenReturn(mock(MetricsManager));
initMocks(this);
activityController.setup();
}
}
I have tried the following suggested solution, but now this error occurs:
I have modified my code according to your suggestion and threw the following error. When executing this line, activitycontroller activitycontroller = robolectric. Buildactivity (testmyactivity. Class);
java.lang.RuntimeException:java.lang.NoSuchMethodException:Tests $TestMyActivity.()
at org.robolectric.util.ReflectionHelpers.callConstructor(ReflectionHelpers.java:233)
at org.robolectric.util.ActivityController.of(ActivityController.java:27)
at org.robolectric.Robolectric.buildActivity(Robolectric.java:42)
at Tests$TestMyActivity.setUp(RegistrationTest.java:89)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
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.RunBefores.evaluate(RunBefores.java:24)
resolvent:
First, storagemanager is not a field or a field passed by constructor, so @ injectmocks has no effect
I will refactor the activity to use better Di, but a simple victory will be:
public class MyActivity extends ... {
@VisibleForTest
@RestrictTo(Scope.TESTS)
protected StorageManager GetStorageManager() {
...
}
}
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class MyActivityTest {
@Mock
private StorageManager storageManagerMock;
MyActivity myActivity;
@Before
public void setUp() {
initMocks(this);
ActivityController<TestMyActivity> activityController = Robolectric.buildActivity(TestMyActivity.class);
myActivity = activityController.get();
// when(registrationActivity.GetMetricManager()).thenReturn(mock(MetricsManager));
activityController.setup();
}
...
public class TestMyActivity extends MyActivity {
protected StorageManager GetStorageManager() {
return storageManagerMock;
}
}
}
This should be slightly modified