Zis
Zis

Reputation: 170

Android Integration tests without emulator

I am wondering if there is an option to test client library which uses Android (mock) and calls backend running on some endpoint?

The use case could be:

Have a library called 'A' that requires android's context (extracts data from it) and Google Services (could be mock). Then call A.sendData(context) that collects data such as advertising id, phone info, ...

So the test lifecycle could be:

A.sendData(context) → waits for server response → assert result.

I've read everywhere that Robolectric can't be used as an integration framework. I've created an Instrumented test with some UI which did the trick BUT running it takes ages and doesn't work properly on remote CI (timeouts, sometimes it passes sometimes it doesn't).

I need to mock 'just' part of Android device (no need for UI) and test if backend returns valid data so probably no need for emulator. OR if the emulator is needed I would like to create a test that uses emulator but there is no need to write UI test.

Is out there anything like this?

Upvotes: 0

Views: 1471

Answers (1)

DeeV
DeeV

Reputation: 36035

It seems to me all you're trying to do is validate a network component sends the appropriate data to a server and handles the appropriate response. For this kind of test, I think Robolectric would suit the needs just fine. It should be able to fill the Context of your app which can then be injected in to your component. All while being run through the JUnit framework which is significantly faster than instrumentation tests.

Though, if all you're trying to do is make sure your network component works. Then you may not actually need the Android framework. You could instead rewrite your class using pure Java. Just strip out the items you need from Context, and inject those in to your classes. Then you can use the JUnit testing framework which runs on the computer instead of the device. It's much faster and doesn't require a phone. This works as long as they're not Android specific components such as Drawable. This will also not work if you require Google Services.

A very tedious method is to use Mockito and PowerMock to mock the methods of your Context and Play Services. You just mock the methods that your Context class is going to use. This can get really complicated though. You can use this alongside Robolectric so you only have to mock what you need to mock.

As far as integrations tests are concerned, there's absolutely no need to write a UI test when writing integration tests. Basically what the integration tests do is create a test Application that runs on the phone. If you don't provide an UI, then you won't use an UI. It'll just show a blank screen while the test runs. You can use InstrumentationRegistery#getContext() to retrieve the context that's used in your application. Then inject the context in to your components that need it.

Though, this can sometimes even be a pain and instrumentation tests take longer even without any UI. But, if you want to make sure it works with an actual Android Context with actual Google Services, this is the best way.

So the basic strategy is to write a whole bunch of small, fast unit tests using Robolectric on JUnit framework which can be run a bunch of times. Then write your comprehensive validation tests using instrumentation framework to make sure everything works together nicely.

Upvotes: 2

Related Questions