49

I have a small app that interacts with a remote android service. I would like to mock that service in unit tests. I use Robolectric and JUnit for other test cases and shadows but I could not figure how to deal with remote services.

Is it sufficient to create and start a test service using the same package with the real service and export methods using same aidl?

Since I don't have the code for that service, I assume that I can not use Robolectric's ShadowService which requires actual class to be there.

Thanks a lot.

Stanley Ko
  • 3,383
  • 3
  • 34
  • 60
Anders T.
  • 499
  • 4
  • 4
  • I think your links are broken. – PunDefeated Dec 01 '15 at 20:33
  • Are you testing the remote service or the small app that is interacting with the remote android service? If you are testing the app, I would start by coding to an interface. All calls to the remote service should be done with the interface. Your small app would have an implementation of the interface that actually calls the remote service. Your test package would have a second implementation that mocks the information returned from the remote service. Each test could configure some backing in memory data that is used by the test packages implementation. – Dan King Dec 05 '15 at 04:15
  • I haven't done something like this in android but have with spring in other java applications so I'm unsure of an exact solution. – Dan King Dec 05 '15 at 04:20
  • Did you find a solution? The best we've come up with before for testing is "AIDL either works or it doesn't, no need to test it" (Now testing the 'service' behind the AIDL... that is a different issue entirely.) and I'm curious to see what is viable for blackbox testing aidl services – mawalker Dec 20 '15 at 09:02

2 Answers2

2

I would use Mockito to create a Mock of the interface and then pass that instance to your code in your tests. You could also manually create an implementation of that interface in your test code and use that.

So you have to do the mocking yourself and it is important that the code you want to tests uses some form of dependency injection to aquire a reference to the aidl interface, so you can pass your own mock in your tests.

Jeroen
  • 3,399
  • 1
  • 22
  • 25
1

If you want to write a unit test for service then you can use Mockito for mocking service behavior.If you want to test your service on the real device then this is how you can connect with your service.

@RunWith(AndroidJUnit4.class)
public classRemoteProductServiceTest {
    @Rule
    public final ServiceTestRule mServiceRule = new ServiceTestRule();
    @Test
    public void testWithStartedService() throws TimeoutException {
        mServiceRule.startService(
                new Intent(InstrumentationRegistry.getTargetContext(), ProductService.class));
        //do something
    }
    @Test
    public void testWithBoundService() throws TimeoutException, RemoteException {
        IBinder binder = mServiceRule.bindService(
                new Intent(InstrumentationRegistry.getTargetContext(), ProductService.class));
        IRemoteProductService iRemoteProductService = IRemoteProductService.Stub.asInterface(binder);
        assertNotNull(iRemoteProductService);
        iRemoteProductService.addProduct("tanvi", 12, 12.2f);
     assertEquals(iRemoteProductService.getProduct("tanvi").getQuantity(), 12);
    }
}
Jens
  • 67,715
  • 15
  • 98
  • 113
user3219477
  • 134
  • 3
  • 10