How to write Android Service unit tests with Robolectric

Viewed 2215

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();
    }
    ...
}
0 Answers
Related