Matt Logan
Matt Logan

Reputation: 5926

Injecting mock Retrofit API service instance into ActivityInstrumentTestCase2

I'd like to write functional tests with Espresso for an Activity using a mock Retrofit API service instance created with a MockRestAdapter (https://github.com/square/retrofit/blob/master/retrofit-mock/src/main/java/retrofit/MockRestAdapter.java).

This is a bit tricky though, as you can't really ever inject any dependencies via the Activity's constructor.

Currently, a single Retrofit API service instance lives in my Application object, and I create a reference to it in each of my Activities' onCreate() methods.

How can I swap in a mock Retrofit API service? Perhaps Dagger is the answer?

Upvotes: 3

Views: 2434

Answers (1)

mindeh
mindeh

Reputation: 1818

Yes, Dagger is the answer. On how to achieve this, I recommend to look at Jake Wharton's u2020 at Github. In a nutshell, you provide different API implementations for production and debug flavors. Or, you could have a separate flavor for integration tests.

Another way to solve this without Dagger (adding support for it would be quite an undertaking for ongoing project), would be to have a flavor for integration tests. E.g. to have release, debug and mock flavors.

Then you could have a different Application class set in Android Manifest for mock flavor - an implementation which uses mock adapter. Core idea here is that you can override or augment you main AndroidManifest in flavors.

That'd roughly look like this:

Project structure

app/
    src/
       main/
           AndroidManifest.xml - Activities, services, permissions - all the stuff goes here 
           java/.../MyApplication.java
       mock/
           AndroidManifest.xml - example below
           java/.../MockApplication.java
       debug/    - Not relevant for this example
       release/  - Not relevant for this example

main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.android" >

    <!-- Permissions etc -->

    <application
        android:name=".MyApplication"
        ...
        >

        <!-- Activities, services etc -->

    </application>
</manifest>

mock/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application android:name=".MockApplication"/>
</manifest>

Application.java

public class MyApplication extends Application {

    @Override public void onCreate(Bundle savedState) {
        MyApi api = createApiAdapter();
    }

    protected MyApi createApiAdapter() {
        // Create regular Retrofit adapter
    }

}

MockApplication.java

public class MockApplication extends MyApplication {

    @Override protected MyApi createApiAdapter() {
        // Create mock Retrofit adapter
    }

}

build.gradle

android {

    // ...

    buildTypes {
        mock {
            applicationIdSuffix '.mock'
            versionNameSuffix '-mock'
            debuggable true
        }
        debug {
            applicationIdSuffix '.dev'
            versionNameSuffix '-dev'
            debuggable true
        }
        release {
            signingConfig signingConfigs.release
        }
    }
}

Upvotes: 6

Related Questions