While covering my complete Android project with tests I am trying to find a way to tests my services with Robolectric. The services I need to test contain a lot of logic an need to be tested.
After some research I found a code example from robolectric how to test a service with shadowService but still I don't know how to start the service and test its functionality.
First I want to create mock of all dependencies and inject them into the service. Then for each method I would like to write tests and that the service with different mocked dependency methods.
How can I do that? What is best practice while testing Android Services? Does anybody knows some good How-to's?
My test and Service so far but the service is not starting(debugger wont step into break point inside the service):
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class , sdk = 23)
public class MyServiceTest {
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock
Context context;
@Mock
ApiService apiService;
@Mock
ServiceManagerImpl serviceManager;
@InjectMocks
private MyService myService;
private ShadowService shadowService;
@Before
public void setUp(){
// explicit service creation from robolectric example
this.updateService = Robolectric.setupService(UpdateService.class);
this.shadowService = shadowOf(this.updateService);
MockitoAnnotations.initMocks(this);
when(this.apiService.fetchData()).thenReturn(42);
}
@Test
public void testService(){
this.updateService.startService(new Intent());
// Test of a service function here ...
}
}
Example of my service:
public class UpdateService extends Service {
@Inject
Context context;
@Inject
ApiService apiService;
@Inject
ServiceManager serviceManager;
private List<ApkRelease> fetchedData;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
((MyApplication) getApplication()).getComponent().inject(this);
this.fetchData();
return super.onStartCommand(intent, flags, startId);
}
private void fetchData() {
Call<List<Data>> call = this.apiService.getData();
call.enqueue(new Callback<List<Data>>() {
@Override
public void onResponse(Call<List<Data>> call, Response<List<Data>> response) {
if (response.body() != null) {
if (!response.body().isEmpty()) {
fetcheData = response.body();
processNextData();
} else {
stopSelf();
}
}
}
@Override
public void onFailure(Call<List<Data>> call, Throwable t) {
ACRA.getErrorReporter().handleException(t);
startUpgrade();
}
});
}
private void processNextData() {
if (this.fetchedData.isEmpty()) {
startOtherStuff();
return;
}
this.processData(this.fetchedReleases.remove(0));
}
private void processData(Data data, ResponseBody responseBody) {
//process Data
....
this.processNextData();
}
private void startOtherStuff() {
Intent intent = new Intent(this.context, UpgradeService.class);
this.context.startService(intent);
this.stopSelf();
}
...
}